Last active
January 5, 2022 12:08
-
-
Save vankxr/a7acad10b0ddfe273724b21b2dd46c1d to your computer and use it in GitHub Desktop.
Read HP Common slot PSUs via I2C from NodeJS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const I2C = require("i2c-bus"); | |
function psu_calc_checksum(addr, buf) | |
{ | |
let cs = (addr << 1); | |
for(let i = 0; i < buf.length - 1; i++) | |
cs += buf.readUInt8(i); | |
buf.writeUInt8(((0xFF - cs) + 1) & 0xFF, buf.length - 1); | |
} | |
function psu_check_checksum(buf) | |
{ | |
let cs = 0; | |
for(let i = 0; i < buf.length; i++) | |
cs += buf.readUInt8(i); | |
if((((0xFF - cs) + 1) & 0xFF) === 0) | |
return true; | |
return false; | |
} | |
async function psu_write_reg(bus, addr, reg, data) | |
{ | |
let buf = Buffer.alloc(4, 0); | |
buf.writeUInt8(reg, 0); | |
buf.writeUInt16LE(data, 1); | |
psu_calc_checksum(addr, buf); | |
return bus.i2cWrite(addr, buf.length, buf); | |
} | |
async function psu_read_reg(bus, addr, reg) | |
{ | |
let buf = Buffer.alloc(2, 0); | |
buf.writeUInt8(reg, 0); | |
psu_calc_checksum(addr, buf); | |
await bus.i2cWrite(addr, buf.length, buf); | |
buf = Buffer.alloc(3, 0); | |
let result = await bus.i2cRead(addr, 3, buf); | |
if(!result) | |
return 0; | |
if(result.bytesRead < 3) | |
return 0; | |
if(!psu_check_checksum(result.buffer)) | |
return 0; | |
return result.buffer.readUInt16LE(0); | |
} | |
async function psu_read_eeprom(bus, addr, mem_addr, count) | |
{ | |
let buf = Buffer.alloc(1, 0); | |
buf.writeUInt8(mem_addr, 0); | |
await bus.i2cWrite(addr, buf.length, buf); | |
buf = Buffer.alloc(count, 0); | |
let result = await bus.i2cRead(addr, count, buf); | |
if(!result) | |
return 0; | |
if(result.bytesRead < count) | |
return 0; | |
return result.buffer; | |
} | |
async function main() | |
{ | |
const psu_ee_addr = 0x57; | |
const psu_addr = 0x5F; | |
const I2C0 = await I2C.openPromisified(0); | |
let found = await I2C0.scan(); | |
if(found.indexOf(psu_addr) === -1) | |
return console.log("PSU not found at address %d", psu_addr); | |
if(found.indexOf(psu_ee_addr) === -1) | |
return console.log("PSU EEPROM not found at address %d", psu_ee_addr); | |
console.log("PSU found at address %d", psu_addr); | |
console.log("PSU EEPROM found at address %d", psu_ee_addr); | |
console.log("-----------------"); | |
let psu_spn = await psu_read_eeprom(I2C0, psu_ee_addr, 0x12, 10); | |
let psu_date = await psu_read_eeprom(I2C0, psu_ee_addr, 0x1D, 8); | |
let psu_name = await psu_read_eeprom(I2C0, psu_ee_addr, 0x32, 26); | |
let psu_ct = await psu_read_eeprom(I2C0, psu_ee_addr, 0x5B, 14); | |
console.log("PSU SPN: %s", psu_spn.toString("utf8")); | |
console.log("PSU Date: %s", psu_date.toString("utf8")); | |
console.log("PSU Name: %s", psu_name.toString("utf8")); | |
console.log("PSU CT: %s", psu_ct.toString("utf8")); | |
let in_v = await psu_read_reg(I2C0, psu_addr, 0x08) / 32; | |
let in_a = await psu_read_reg(I2C0, psu_addr, 0x0A) / 256; | |
let in_a_max = await psu_read_reg(I2C0, psu_addr, 0x34) / 256; | |
let in_w = await psu_read_reg(I2C0, psu_addr, 0x0C) / 4; | |
let in_w_max = await psu_read_reg(I2C0, psu_addr, 0x32) / 4; | |
let in_ws = (await psu_read_reg(I2C0, psu_addr, 0x2C) + (await psu_read_reg(I2C0, psu_addr, 0x2E) << 16)) / 4; | |
let out_v = await psu_read_reg(I2C0, psu_addr, 0x0E) / 256; | |
let out_a = await psu_read_reg(I2C0, psu_addr, 0x10) / 64; | |
let out_a_max = await psu_read_reg(I2C0, psu_addr, 0x36) / 64; | |
let out_w = await psu_read_reg(I2C0, psu_addr, 0x12) / 4; | |
let intake_temp = await psu_read_reg(I2C0, psu_addr, 0x1A) / 64; | |
let internal_temp = await psu_read_reg(I2C0, psu_addr, 0x1C) / 64; | |
let fan_rpm = await psu_read_reg(I2C0, psu_addr, 0x1E); | |
let fan_target_rpm = await psu_read_reg(I2C0, psu_addr, 0x40); | |
let on_time = await psu_read_reg(I2C0, psu_addr, 0x30); | |
let status_flags = await psu_read_reg(I2C0, psu_addr, 0x02); | |
console.log("Input Voltage: %d V", in_v); | |
console.log("Input Current: %d A (max. %d A)", in_a, in_a_max); | |
console.log("Input Power: %d W (max. %d W)", in_w, in_w_max); | |
console.log("Input Energy: %d kWh", in_ws / 3600000); | |
console.log("Output Voltage: %d V", out_v); | |
console.log("Output Current: %d A (max. %d A)", out_a, out_a_max); | |
console.log("Output Power: %d W", out_w); | |
console.log("Intake Temperature: %d C", intake_temp); | |
console.log("Internal Temperature: %d C", internal_temp); | |
console.log("Fan speed: %d RPM", fan_rpm); | |
console.log("Fan target speed: %d RPM", fan_target_rpm); | |
console.log("On time: %d s", on_time); | |
console.log("Status flags: %d", status_flags); | |
console.log("PSU ON: " + ((status_flags & 0x05) === 0x05)); | |
psu_write_reg(I2C0, psu_addr, 0x40, 0); | |
} | |
main(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment