001package com.pi4j.system; 002 003/* 004 * #%L 005 * ********************************************************************** 006 * ORGANIZATION : Pi4J 007 * PROJECT : Pi4J :: Java Library (Core) 008 * FILENAME : SystemInfo.java 009 * 010 * This file is part of the Pi4J project. More information about 011 * this project can be found here: http://www.pi4j.com/ 012 * ********************************************************************** 013 * %% 014 * Copyright (C) 2012 - 2013 Pi4J 015 * %% 016 * Licensed under the Apache License, Version 2.0 (the "License"); 017 * you may not use this file except in compliance with the License. 018 * You may obtain a copy of the License at 019 * 020 * http://www.apache.org/licenses/LICENSE-2.0 021 * 022 * Unless required by applicable law or agreed to in writing, software 023 * distributed under the License is distributed on an "AS IS" BASIS, 024 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 025 * See the License for the specific language governing permissions and 026 * limitations under the License. 027 * #L% 028 */ 029 030 031import java.io.IOException; 032import java.security.AccessController; 033import java.security.PrivilegedAction; 034import java.text.ParseException; 035import java.util.ArrayList; 036import java.util.HashMap; 037import java.util.List; 038import java.util.Map; 039 040import com.pi4j.util.ExecUtil; 041import com.pi4j.util.StringUtil; 042 043public class SystemInfo { 044 045 // private constructor 046 private SystemInfo() { 047 // forbid object construction 048 } 049 050 public enum BoardType { 051 UNKNOWN, 052 ModelA_Rev0, 053 ModelB_Rev1, 054 ModelB_Rev2 055 } 056 057 private static Map<String, String> cpuInfo; 058 059 private static String getCpuInfo(String target) throws IOException, InterruptedException { 060 // if the CPU data has not been previously acquired, then acquire it now 061 if (cpuInfo == null) { 062 cpuInfo = new HashMap<String, String>(); 063 String result[] = ExecUtil.execute("cat /proc/cpuinfo"); 064 if(result != null){ 065 for(String line : result) { 066 String parts[] = line.split(":", 2); 067 if (parts.length >= 2 && !parts[0].trim().isEmpty() && !parts[1].trim().isEmpty()) { 068 cpuInfo.put(parts[0].trim(), parts[1].trim()); 069 } 070 } 071 } 072 } 073 074 if (cpuInfo.containsKey(target)) { 075 return cpuInfo.get(target); 076 } 077 078 throw new RuntimeException("Invalid target: " + target); 079 } 080 081 public static String getProcessor() throws IOException, InterruptedException { 082 return getCpuInfo("Processor"); 083 } 084 085 public static String getBogoMIPS() throws IOException, InterruptedException { 086 return getCpuInfo("BogoMIPS"); 087 } 088 089 public static String[] getCpuFeatures() throws IOException, InterruptedException { 090 return getCpuInfo("Features").split(" "); 091 } 092 093 public static String getCpuImplementer() throws IOException, InterruptedException { 094 return getCpuInfo("CPU implementer"); 095 } 096 097 public static String getCpuArchitecture() throws IOException, InterruptedException { 098 return getCpuInfo("CPU architecture"); 099 } 100 101 public static String getCpuVariant() throws IOException, InterruptedException { 102 return getCpuInfo("CPU variant"); 103 } 104 105 public static String getCpuPart() throws IOException, InterruptedException { 106 return getCpuInfo("CPU part"); 107 } 108 109 public static String getCpuRevision() throws IOException, InterruptedException { 110 return getCpuInfo("CPU revision"); 111 } 112 113 public static String getHardware() throws IOException, InterruptedException { 114 return getCpuInfo("Hardware"); 115 } 116 117 public static String getRevision() throws IOException, InterruptedException { 118 return getCpuInfo("Revision"); 119 } 120 121 public static String getSerial() throws IOException, InterruptedException { 122 return getCpuInfo("Serial"); 123 } 124 125 public static String getOsName() { 126 return System.getProperty("os.name"); 127 } 128 129 public static String getOsVersion() { 130 return System.getProperty("os.version"); 131 } 132 133 public static String getOsArch() { 134 return System.getProperty("os.arch"); 135 } 136 137 public static String getOsFirmwareBuild() throws IOException, InterruptedException { 138 String result[] = ExecUtil.execute("/opt/vc/bin/vcgencmd version"); 139 if(result != null){ 140 for(String line : result) { 141 if(line.startsWith("version ")){ 142 return line.substring(8); 143 } 144 } 145 } 146 throw new RuntimeException("Invalid command or response."); 147 } 148 149 public static String getOsFirmwareDate() throws IOException, InterruptedException, ParseException { 150 String result[] = ExecUtil.execute("/opt/vc/bin/vcgencmd version"); 151 if(result != null){ 152 for(String line : result) { 153 return line; // return 1st line 154 } 155 } 156 throw new RuntimeException("Invalid command or response."); 157 } 158 159 public static String getJavaVendor() { 160 return System.getProperty("java.vendor"); 161 } 162 163 public static String getJavaVendorUrl() { 164 return System.getProperty("java.vendor.url"); 165 } 166 167 public static String getJavaVersion() { 168 return System.getProperty("java.version"); 169 } 170 171 public static String getJavaVirtualMachine() { 172 return System.getProperty("java.vm.name"); 173 } 174 175 public static String getJavaRuntime() { 176 return AccessController.doPrivileged(new PrivilegedAction<String>() { 177 public String run() { 178 return System.getProperty("java.runtime.name"); 179 } 180 }); 181 } 182 183 /* 184 * this method was partially derived from :: (project) jogamp / (developer) sgothel 185 * https://github.com/sgothel/gluegen/blob/master/src/java/jogamp/common/os/PlatformPropsImpl.java#L160 186 * https://github.com/sgothel/gluegen/blob/master/LICENSE.txt 187 */ 188 public static boolean isHardFloatAbi() { 189 190 return AccessController.doPrivileged(new PrivilegedAction<Boolean>() { 191 private final String[] gnueabihf = new String[] { "gnueabihf", "armhf" }; 192 public Boolean run() { 193 if ( StringUtil.contains(System.getProperty("sun.boot.library.path"), gnueabihf) || 194 StringUtil.contains(System.getProperty("java.library.path"), gnueabihf) || 195 StringUtil.contains(System.getProperty("java.home"), gnueabihf) || 196 getBashVersionInfo().contains("gnueabihf") || 197 hasReadElfTag("Tag_ABI_HardFP_use")) { 198 return true; // 199 } 200 return false; 201 } } ); 202 } 203 204 205 private static List<Long> getMemory() throws IOException, InterruptedException { 206 // Memory information is in the form 207 // root@mypi:/home/pi# free -b 208 // total used free shared buffers cached 209 // Mem: 459771904 144654336 315117568 0 21319680 63713280 210 // -/+ buffers/cache: 59621376 400150528 211 // Swap: 104853504 0 104853504 212 List<Long> values = new ArrayList<>(); 213 String result[] = ExecUtil.execute("free -b"); 214 if(result != null){ 215 for(String line : result) { 216 if(line.startsWith("Mem:")){ 217 String parts[] = line.split(" "); 218 for(String part : parts){ 219 part = part.trim(); 220 if(!part.isEmpty() && !part.equalsIgnoreCase("Mem:")){ 221 values.add(new Long(part)); 222 } 223 } 224 } 225 } 226 } 227 return values; 228 } 229 230 public static long getMemoryTotal() throws IOException, InterruptedException { 231 List<Long> values = getMemory(); 232 if(!values.isEmpty() && values.size() > 0){ 233 return values.get(0); // total memory value is in first position 234 } 235 return -1; 236 } 237 238 public static long getMemoryUsed() throws IOException, InterruptedException { 239 List<Long> values = getMemory(); 240 if(!values.isEmpty() && values.size() > 1){ 241 return values.get(1); // used memory value is in second position 242 } 243 return -1; 244 } 245 246 public static long getMemoryFree() throws IOException, InterruptedException { 247 List<Long> values = getMemory(); 248 if(!values.isEmpty() && values.size() > 2){ 249 return values.get(2); // free memory value is in third position 250 } 251 return -1; 252 } 253 254 public static long getMemoryShared() throws IOException, InterruptedException { 255 List<Long> values = getMemory(); 256 if(!values.isEmpty() && values.size() > 3){ 257 return values.get(3); // shared memory value is in fourth position 258 } 259 return -1; 260 } 261 262 public static long getMemoryBuffers() throws IOException, InterruptedException { 263 List<Long> values = getMemory(); 264 if(!values.isEmpty() && values.size() > 4){ 265 return values.get(4); // buffers memory value is in fifth position 266 } 267 return -1; 268 } 269 270 public static long getMemoryCached() throws IOException, InterruptedException { 271 List<Long> values = getMemory(); 272 if(!values.isEmpty() && values.size() > 5){ 273 return values.get(5); // cached memory value is in sixth position 274 } 275 return -1; 276 } 277 278 public static BoardType getBoardType() throws IOException, InterruptedException 279 { 280 // The following info obtained from: 281 // http://www.raspberrypi.org/archives/1929 282 // http://raspberryalphaomega.org.uk/?p=428 283 // http://www.raspberrypi.org/phpBB3/viewtopic.php?p=281039#p281039 284 switch(getRevision()) 285 { 286 case "0002": // Model B Revision 1 287 case "0003": // Model B Revision 1 + Fuses mod and D14 removed 288 return BoardType.ModelB_Rev1; 289 case "0004": // Model B Revision 2 256MB (Sony) 290 case "0005": // Model B Revision 2 256MB (Qisda) 291 case "0006": // Model B Revision 2 256MB (Egoman) 292 return BoardType.ModelB_Rev2; 293 case "0007": // Model A 256MB (Egoman) 294 case "0008": // Model A 256MB (Sony) 295 case "0009": // Model A 256MB (Qisda) 296 return BoardType.ModelA_Rev0; 297 case "000d": // Model B Revision 2 512MB (Egoman) 298 case "000e": // Model B Revision 2 512MB (Sony) 299 case "000f": // Model B Revision 2 512MB (Qisda) 300 return BoardType.ModelB_Rev2; 301 default: 302 return BoardType.UNKNOWN; 303 } 304 } 305 306 public static float getCpuTemperature() throws IOException, InterruptedException, NumberFormatException { 307 // CPU temperature is in the form 308 // pi@mypi$ /opt/vc/bin/vcgencmd measure_temp 309 // temp=42.3'C 310 // Support for this was added around firmware version 3357xx per info 311 // at http://www.raspberrypi.org/phpBB3/viewtopic.php?p=169909#p169909 312 String result[] = ExecUtil.execute("/opt/vc/bin/vcgencmd measure_temp"); 313 if(result != null){ 314 for(String line : result) { 315 String parts[] = line.split("[=']", 3); 316 return Float.parseFloat(parts[1]); 317 } 318 } 319 throw new RuntimeException("Invalid command or response."); 320 } 321 322 private static float getVoltage(String id) throws IOException, InterruptedException, NumberFormatException { 323 String result[] = ExecUtil.execute("/opt/vc/bin/vcgencmd measure_volts " + id); 324 if(result != null){ 325 for(String line : result) { 326 String parts[] = line.split("[=V]", 3); 327 return Float.parseFloat(parts[1]); 328 } 329 } 330 throw new RuntimeException("Invalid command or response."); 331 } 332 333 public static float getCpuVoltage() throws IOException, InterruptedException, NumberFormatException { 334 return getVoltage("core"); 335 } 336 337 public static float getMemoryVoltageSDRam_C() throws IOException, InterruptedException, NumberFormatException { 338 return getVoltage("sdram_c"); 339 } 340 341 public static float getMemoryVoltageSDRam_I() throws IOException, InterruptedException, NumberFormatException { 342 return getVoltage("sdram_i"); 343 } 344 345 public static float getMemoryVoltageSDRam_P() throws IOException, InterruptedException, NumberFormatException { 346 return getVoltage("sdram_p"); 347 } 348 349 350 private static boolean getCodecEnabled(String codec) throws IOException, InterruptedException { 351 String result[] = ExecUtil.execute("/opt/vc/bin/vcgencmd codec_enabled " + codec); 352 if(result != null){ 353 for(String line : result) { 354 String parts[] = line.split("=", 2); 355 return parts[1].trim().equalsIgnoreCase("enabled"); 356 } 357 } 358 throw new RuntimeException("Invalid command or response."); 359 } 360 361 public static boolean getCodecH264Enabled() throws IOException, InterruptedException { 362 return getCodecEnabled("H264"); 363 } 364 365 public static boolean getCodecMPG2Enabled() throws IOException, InterruptedException { 366 return getCodecEnabled("MPG2"); 367 } 368 369 public static boolean getCodecWVC1Enabled() throws IOException, InterruptedException { 370 return getCodecEnabled("WVC1"); 371 } 372 373 374 private static long getClockFrequency(String target) throws IOException, InterruptedException { 375 String result[] = ExecUtil.execute("/opt/vc/bin/vcgencmd measure_clock " + target.trim()); 376 if(result != null){ 377 for(String line : result) { 378 String parts[] = line.split("=", 2); 379 return Long.parseLong(parts[1].trim()); 380 } 381 } 382 throw new RuntimeException("Invalid command or response."); 383 } 384 385 public static long getClockFrequencyArm() throws IOException, InterruptedException { 386 return getClockFrequency("arm"); 387 } 388 389 public static long getClockFrequencyCore() throws IOException, InterruptedException { 390 return getClockFrequency("core"); 391 } 392 393 public static long getClockFrequencyH264() throws IOException, InterruptedException { 394 return getClockFrequency("h264"); 395 } 396 397 public static long getClockFrequencyISP() throws IOException, InterruptedException { 398 return getClockFrequency("isp"); 399 } 400 401 public static long getClockFrequencyV3D() throws IOException, InterruptedException { 402 return getClockFrequency("v3d"); 403 } 404 405 public static long getClockFrequencyUART() throws IOException, InterruptedException { 406 return getClockFrequency("uart"); 407 } 408 409 public static long getClockFrequencyPWM() throws IOException, InterruptedException { 410 return getClockFrequency("pwm"); 411 } 412 413 public static long getClockFrequencyEMMC() throws IOException, InterruptedException { 414 return getClockFrequency("emmc"); 415 } 416 417 public static long getClockFrequencyPixel() throws IOException, InterruptedException { 418 return getClockFrequency("pixel"); 419 } 420 421 public static long getClockFrequencyVEC() throws IOException, InterruptedException { 422 return getClockFrequency("vec"); 423 } 424 425 public static long getClockFrequencyHDMI() throws IOException, InterruptedException { 426 return getClockFrequency("hdmi"); 427 } 428 429 public static long getClockFrequencyDPI() throws IOException, InterruptedException { 430 return getClockFrequency("dpi"); 431 } 432 433 434 /* 435 * this method will to obtain the version info string from the 'bash' program 436 * (this method is used to help determine the HARD-FLOAT / SOFT-FLOAT ABI of the system) 437 */ 438 private static String getBashVersionInfo() { 439 String versionInfo = ""; 440 try { 441 String result[] = ExecUtil.execute("bash --version"); 442 for(String line : result) { 443 if(!line.isEmpty()) { 444 versionInfo = line; // return only first output line of version info 445 break; 446 } 447 } 448 } 449 catch (IOException ioe) { ioe.printStackTrace(); } 450 catch (InterruptedException ie) { ie.printStackTrace(); } 451 return versionInfo; 452 } 453 454 /* 455 * this method will determine if a specified tag exists from the elf info in the '/proc/self/exe' program 456 * (this method is used to help determine the HARD-FLOAT / SOFT-FLOAT ABI of the system) 457 */ 458 private static boolean hasReadElfTag(String tag) { 459 String tagValue = getReadElfTag(tag); 460 if(tagValue != null && !tagValue.isEmpty()) 461 return true; 462 return false; 463 } 464 465 /* 466 * this method will obtain a specified tag value from the elf info in the '/proc/self/exe' program 467 * (this method is used to help determine the HARD-FLOAT / SOFT-FLOAT ABI of the system) 468 */ 469 private static String getReadElfTag(String tag) { 470 String tagValue = null; 471 try { 472 String result[] = ExecUtil.execute("/usr/bin/readelf -A /proc/self/exe"); 473 if(result != null){ 474 for(String line : result) { 475 line = line.trim(); 476 if (line.startsWith(tag) && line.contains(":")) { 477 String lineParts[] = line.split(":", 2); 478 if(lineParts.length > 1) 479 tagValue = lineParts[1].trim(); 480 break; 481 } 482 } 483 } 484 } 485 catch (IOException ioe) { ioe.printStackTrace(); } 486 catch (InterruptedException ie) { ie.printStackTrace(); } 487 return tagValue; 488 } 489}