package com.pi4j.system;
/*
* #%L
* **********************************************************************
* ORGANIZATION : Pi4J
* PROJECT : Pi4J :: Java Library (Core)
* FILENAME : SystemInfo.java
*
* This file is part of the Pi4J project. More information about
* this project can be found here: http://www.pi4j.com/
* **********************************************************************
* %%
* Copyright (C) 2012 - 2013 Pi4J
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import java.io.IOException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.pi4j.util.ExecUtil;
import com.pi4j.util.StringUtil;
public class SystemInfo {
// private constructor
private SystemInfo() {
// forbid object construction
}
public enum BoardType {
UNKNOWN,
ModelA_Rev0,
ModelB_Rev1,
ModelB_Rev2
}
private static Map<String, String> cpuInfo;
private static String getCpuInfo(String target) throws IOException, InterruptedException {
// if the CPU data has not been previously acquired, then acquire it now
if (cpuInfo == null) {
cpuInfo = new HashMap<String, String>();
String result[] = ExecUtil.execute("cat /proc/cpuinfo");
if(result != null){
for(String line : result) {
String parts[] = line.split(":", 2);
if (parts.length >= 2 && !parts[0].trim().isEmpty() && !parts[1].trim().isEmpty()) {
cpuInfo.put(parts[0].trim(), parts[1].trim());
}
}
}
}
if (cpuInfo.containsKey(target)) {
return cpuInfo.get(target);
}
throw new RuntimeException("Invalid target: " + target);
}
public static String getProcessor() throws IOException, InterruptedException {
return getCpuInfo("Processor");
}
public static String getBogoMIPS() throws IOException, InterruptedException {
return getCpuInfo("BogoMIPS");
}
public static String[] getCpuFeatures() throws IOException, InterruptedException {
return getCpuInfo("Features").split(" ");
}
public static String getCpuImplementer() throws IOException, InterruptedException {
return getCpuInfo("CPU implementer");
}
public static String getCpuArchitecture() throws IOException, InterruptedException {
return getCpuInfo("CPU architecture");
}
public static String getCpuVariant() throws IOException, InterruptedException {
return getCpuInfo("CPU variant");
}
public static String getCpuPart() throws IOException, InterruptedException {
return getCpuInfo("CPU part");
}
public static String getCpuRevision() throws IOException, InterruptedException {
return getCpuInfo("CPU revision");
}
public static String getHardware() throws IOException, InterruptedException {
return getCpuInfo("Hardware");
}
public static String getRevision() throws IOException, InterruptedException {
return getCpuInfo("Revision");
}
public static String getSerial() throws IOException, InterruptedException {
return getCpuInfo("Serial");
}
public static String getOsName() {
return System.getProperty("os.name");
}
public static String getOsVersion() {
return System.getProperty("os.version");
}
public static String getOsArch() {
return System.getProperty("os.arch");
}
public static String getOsFirmwareBuild() throws IOException, InterruptedException {
String result[] = ExecUtil.execute("/opt/vc/bin/vcgencmd version");
if(result != null){
for(String line : result) {
if(line.startsWith("version ")){
return line.substring(8);
}
}
}
throw new RuntimeException("Invalid command or response.");
}
public static String getOsFirmwareDate() throws IOException, InterruptedException, ParseException {
String result[] = ExecUtil.execute("/opt/vc/bin/vcgencmd version");
if(result != null){
for(String line : result) {
return line; // return 1st line
}
}
throw new RuntimeException("Invalid command or response.");
}
public static String getJavaVendor() {
return System.getProperty("java.vendor");
}
public static String getJavaVendorUrl() {
return System.getProperty("java.vendor.url");
}
public static String getJavaVersion() {
return System.getProperty("java.version");
}
public static String getJavaVirtualMachine() {
return System.getProperty("java.vm.name");
}
public static String getJavaRuntime() {
return AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return System.getProperty("java.runtime.name");
}
});
}
/*
* this method was partially derived from :: (project) jogamp / (developer) sgothel
* https://github.com/sgothel/gluegen/blob/master/src/java/jogamp/common/os/PlatformPropsImpl.java#L160
* https://github.com/sgothel/gluegen/blob/master/LICENSE.txt
*/
public static boolean isHardFloatAbi() {
return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
private final String[] gnueabihf = new String[] { "gnueabihf", "armhf" };
public Boolean run() {
if ( StringUtil.contains(System.getProperty("sun.boot.library.path"), gnueabihf) ||
StringUtil.contains(System.getProperty("java.library.path"), gnueabihf) ||
StringUtil.contains(System.getProperty("java.home"), gnueabihf) ||
getBashVersionInfo().contains("gnueabihf") ||
hasReadElfTag("Tag_ABI_HardFP_use")) {
return true; //
}
return false;
} } );
}
private static List<Long> getMemory() throws IOException, InterruptedException {
// Memory information is in the form
// root@mypi:/home/pi# free -b
// total used free shared buffers cached
// Mem: 459771904 144654336 315117568 0 21319680 63713280
// -/+ buffers/cache: 59621376 400150528
// Swap: 104853504 0 104853504
List<Long> values = new ArrayList<>();
String result[] = ExecUtil.execute("free -b");
if(result != null){
for(String line : result) {
if(line.startsWith("Mem:")){
String parts[] = line.split(" ");
for(String part : parts){
part = part.trim();
if(!part.isEmpty() && !part.equalsIgnoreCase("Mem:")){
values.add(new Long(part));
}
}
}
}
}
return values;
}
public static long getMemoryTotal() throws IOException, InterruptedException {
List<Long> values = getMemory();
if(!values.isEmpty() && values.size() > 0){
return values.get(0); // total memory value is in first position
}
return -1;
}
public static long getMemoryUsed() throws IOException, InterruptedException {
List<Long> values = getMemory();
if(!values.isEmpty() && values.size() > 1){
return values.get(1); // used memory value is in second position
}
return -1;
}
public static long getMemoryFree() throws IOException, InterruptedException {
List<Long> values = getMemory();
if(!values.isEmpty() && values.size() > 2){
return values.get(2); // free memory value is in third position
}
return -1;
}
public static long getMemoryShared() throws IOException, InterruptedException {
List<Long> values = getMemory();
if(!values.isEmpty() && values.size() > 3){
return values.get(3); // shared memory value is in fourth position
}
return -1;
}
public static long getMemoryBuffers() throws IOException, InterruptedException {
List<Long> values = getMemory();
if(!values.isEmpty() && values.size() > 4){
return values.get(4); // buffers memory value is in fifth position
}
return -1;
}
public static long getMemoryCached() throws IOException, InterruptedException {
List<Long> values = getMemory();
if(!values.isEmpty() && values.size() > 5){
return values.get(5); // cached memory value is in sixth position
}
return -1;
}
public static BoardType getBoardType() throws IOException, InterruptedException
{
// The following info obtained from:
// http://www.raspberrypi.org/archives/1929
// http://raspberryalphaomega.org.uk/?p=428
// http://www.raspberrypi.org/phpBB3/viewtopic.php?p=281039#p281039
switch(getRevision())
{
case "0002": // Model B Revision 1
case "0003": // Model B Revision 1 + Fuses mod and D14 removed
return BoardType.ModelB_Rev1;
case "0004": // Model B Revision 2 256MB (Sony)
case "0005": // Model B Revision 2 256MB (Qisda)
case "0006": // Model B Revision 2 256MB (Egoman)
return BoardType.ModelB_Rev2;
case "0007": // Model A 256MB (Egoman)
case "0008": // Model A 256MB (Sony)
case "0009": // Model A 256MB (Qisda)
return BoardType.ModelA_Rev0;
case "000d": // Model B Revision 2 512MB (Egoman)
case "000e": // Model B Revision 2 512MB (Sony)
case "000f": // Model B Revision 2 512MB (Qisda)
return BoardType.ModelB_Rev2;
default:
return BoardType.UNKNOWN;
}
}
public static float getCpuTemperature() throws IOException, InterruptedException, NumberFormatException {
// CPU temperature is in the form
// pi@mypi$ /opt/vc/bin/vcgencmd measure_temp
// temp=42.3'C
// Support for this was added around firmware version 3357xx per info
// at http://www.raspberrypi.org/phpBB3/viewtopic.php?p=169909#p169909
String result[] = ExecUtil.execute("/opt/vc/bin/vcgencmd measure_temp");
if(result != null){
for(String line : result) {
String parts[] = line.split("[=']", 3);
return Float.parseFloat(parts[1]);
}
}
throw new RuntimeException("Invalid command or response.");
}
private static float getVoltage(String id) throws IOException, InterruptedException, NumberFormatException {
String result[] = ExecUtil.execute("/opt/vc/bin/vcgencmd measure_volts " + id);
if(result != null){
for(String line : result) {
String parts[] = line.split("[=V]", 3);
return Float.parseFloat(parts[1]);
}
}
throw new RuntimeException("Invalid command or response.");
}
public static float getCpuVoltage() throws IOException, InterruptedException, NumberFormatException {
return getVoltage("core");
}
public static float getMemoryVoltageSDRam_C() throws IOException, InterruptedException, NumberFormatException {
return getVoltage("sdram_c");
}
public static float getMemoryVoltageSDRam_I() throws IOException, InterruptedException, NumberFormatException {
return getVoltage("sdram_i");
}
public static float getMemoryVoltageSDRam_P() throws IOException, InterruptedException, NumberFormatException {
return getVoltage("sdram_p");
}
private static boolean getCodecEnabled(String codec) throws IOException, InterruptedException {
String result[] = ExecUtil.execute("/opt/vc/bin/vcgencmd codec_enabled " + codec);
if(result != null){
for(String line : result) {
String parts[] = line.split("=", 2);
return parts[1].trim().equalsIgnoreCase("enabled");
}
}
throw new RuntimeException("Invalid command or response.");
}
public static boolean getCodecH264Enabled() throws IOException, InterruptedException {
return getCodecEnabled("H264");
}
public static boolean getCodecMPG2Enabled() throws IOException, InterruptedException {
return getCodecEnabled("MPG2");
}
public static boolean getCodecWVC1Enabled() throws IOException, InterruptedException {
return getCodecEnabled("WVC1");
}
private static long getClockFrequency(String target) throws IOException, InterruptedException {
String result[] = ExecUtil.execute("/opt/vc/bin/vcgencmd measure_clock " + target.trim());
if(result != null){
for(String line : result) {
String parts[] = line.split("=", 2);
return Long.parseLong(parts[1].trim());
}
}
throw new RuntimeException("Invalid command or response.");
}
public static long getClockFrequencyArm() throws IOException, InterruptedException {
return getClockFrequency("arm");
}
public static long getClockFrequencyCore() throws IOException, InterruptedException {
return getClockFrequency("core");
}
public static long getClockFrequencyH264() throws IOException, InterruptedException {
return getClockFrequency("h264");
}
public static long getClockFrequencyISP() throws IOException, InterruptedException {
return getClockFrequency("isp");
}
public static long getClockFrequencyV3D() throws IOException, InterruptedException {
return getClockFrequency("v3d");
}
public static long getClockFrequencyUART() throws IOException, InterruptedException {
return getClockFrequency("uart");
}
public static long getClockFrequencyPWM() throws IOException, InterruptedException {
return getClockFrequency("pwm");
}
public static long getClockFrequencyEMMC() throws IOException, InterruptedException {
return getClockFrequency("emmc");
}
public static long getClockFrequencyPixel() throws IOException, InterruptedException {
return getClockFrequency("pixel");
}
public static long getClockFrequencyVEC() throws IOException, InterruptedException {
return getClockFrequency("vec");
}
public static long getClockFrequencyHDMI() throws IOException, InterruptedException {
return getClockFrequency("hdmi");
}
public static long getClockFrequencyDPI() throws IOException, InterruptedException {
return getClockFrequency("dpi");
}
/*
* this method will to obtain the version info string from the 'bash' program
* (this method is used to help determine the HARD-FLOAT / SOFT-FLOAT ABI of the system)
*/
private static String getBashVersionInfo() {
String versionInfo = "";
try {
String result[] = ExecUtil.execute("bash --version");
for(String line : result) {
if(!line.isEmpty()) {
versionInfo = line; // return only first output line of version info
break;
}
}
}
catch (IOException ioe) { ioe.printStackTrace(); }
catch (InterruptedException ie) { ie.printStackTrace(); }
return versionInfo;
}
/*
* this method will determine if a specified tag exists from the elf info in the '/proc/self/exe' program
* (this method is used to help determine the HARD-FLOAT / SOFT-FLOAT ABI of the system)
*/
private static boolean hasReadElfTag(String tag) {
String tagValue = getReadElfTag(tag);
if(tagValue != null && !tagValue.isEmpty())
return true;
return false;
}
/*
* this method will obtain a specified tag value from the elf info in the '/proc/self/exe' program
* (this method is used to help determine the HARD-FLOAT / SOFT-FLOAT ABI of the system)
*/
private static String getReadElfTag(String tag) {
String tagValue = null;
try {
String result[] = ExecUtil.execute("/usr/bin/readelf -A /proc/self/exe");
if(result != null){
for(String line : result) {
line = line.trim();
if (line.startsWith(tag) && line.contains(":")) {
String lineParts[] = line.split(":", 2);
if(lineParts.length > 1)
tagValue = lineParts[1].trim();
break;
}
}
}
}
catch (IOException ioe) { ioe.printStackTrace(); }
catch (InterruptedException ie) { ie.printStackTrace(); }
return tagValue;
}
}