Interact with I²C Bus
This lambda reads the input voltage on a SixFab UPS Hat. The On Prem CLI is used to demonstrate manually triggering the lambda and taking delivery of the event JSON using a remote desktop.
Note that manually triggering a lambda is unusual in that it requires device connectivity to the control plane. A more typical scenario is where Lambdas and their Lambda Trigger control loops run autonomously at the device edge, regardless of the device's connectivity to the control plane.
Register the lambda
$ onprem generate xid
clut5qm56a1d39be96j0
# get_sixfab_ups_hat_input_voltage.yaml
name: get_sixfab_ups_hat_input_voltage
kind: Lambda
id: clut5qm56a1d39be96j0
description: >
Read the input voltage on a SixFab UPS HAT.
runAt:
deviceId: ci2fabp32ckvhk1g9qe0
scriptContentType: text/x-lua
script: >
local socket = require('socket')
local I2C = require('periphery.I2C')
function lshift(a, b)
return a * 2 ^ b
end
local M={}
function M.handler(event, context)
local i2c = I2C('/dev/i2c-1')
local addr = 0x41
-- send GetInputVoltage (0x02) command
local req = {0xcd, 0x02, 0x01, 0x00, 0x00, 0xc8, 0x9a}
i2c:transfer(addr, { req })
-- wait for HAT to prepare response
socket.sleep(0.01)
-- read response
local res = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, flags=I2C.I2C_M_RD}
i2c:transfer(addr, { res })
-- decode response
local crc_hi, crc_lo = res[2], res[3]
local crc = lshift(crc_hi, 8) + crc_lo
local datalen_hi, datalen_lo = res[4], res[5]
local datalen = lshift(datalen_hi, 8) + datalen_lo
assert(datalen == 4)
local x3, x2, x1, x0 = res[6], res[7], res[8], res[9]
local raw_reading = lshift(x3, 24) + lshift(x2, 16) + lshift(x1, 8) + x0
local voltage = raw_reading / 1000
-- respond
return {voltage=voltage, rawReading=raw_reading, crc=crc}
end
return M
$ onprem apply get_sixfab_ups_hat_input_voltage.yaml
It will now show up in the cloud console.
Invoke it
$ onprem run lambda clut5qm56a1d39be96j0
{"crc":514,"rawReading":4928,"voltage":4.928}