From 5cb534cc64f2806d1f7bbf218569d51cc3239e5a Mon Sep 17 00:00:00 2001 From: rcooke-warwick Date: Tue, 23 Jul 2024 11:00:41 +0100 Subject: [PATCH 1/4] serial: make baud rate configurable and return object This makes the baudrate configurable and makes the opened serial port accessible - so different parts of the test can share and use this single object and avoid conflicts accessing the port. Also adds error handling for when the port can't be opened Change-type: patch Signed-off-by: Ryan Cooke --- .../serial/implementations/ftdi/index.ts | 20 +++++++++++++++---- lib/interfaces.d.ts | 2 +- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/lib/features/serial/implementations/ftdi/index.ts b/lib/features/serial/implementations/ftdi/index.ts index 5e09fc2..84a3cfe 100644 --- a/lib/features/serial/implementations/ftdi/index.ts +++ b/lib/features/serial/implementations/ftdi/index.ts @@ -2,12 +2,13 @@ const SerialPort = require('serialport'); export class Ftdi implements Serial { public DEV_SERIAL = '/dev/ttyUSB0' || process.env.DEV_SERIAL; + public BAUD_RATE = Number(process.env.BAUD_RATE || 115200); public serial : any; - constructor(baudRate = 115200){ + constructor(){ this.serial = new SerialPort( this.DEV_SERIAL, { - baudRate: baudRate, + baudRate: this.BAUD_RATE, autoOpen: false, }); @@ -18,9 +19,20 @@ export class Ftdi implements Serial { async open(){ if(this.serial.isOpen){ - console.log(`Serial already open!`) + console.log(`Serial already open!`); + return this.serial; } else { - this.serial.open(); + try{ + console.log(`Opening Serial port ${this.DEV_SERIAL} with baud rate: ${this.BAUD_RATE}`) + this.serial.open(() => { + console.log('DUT serial is opened'); + this.serial?.flush(); + }) + return this.serial; + } catch(e){ + console.log(e) + } + } } diff --git a/lib/interfaces.d.ts b/lib/interfaces.d.ts index 0a17636..515ae2e 100644 --- a/lib/interfaces.d.ts +++ b/lib/interfaces.d.ts @@ -38,7 +38,7 @@ interface Serial extends Base{ serial: any; write(data: string): Promise; read(): Promise; - open(): Promise; + open(): Promise; close(): Promise; } From 5e8fb69ede821205a3506b124dae51da898b4ec2 Mon Sep 17 00:00:00 2001 From: rcooke-warwick Date: Tue, 23 Jul 2024 12:07:10 +0100 Subject: [PATCH 2/4] flashing: allow for different power off detection mechanisms Allows for the selection of either ethernet carrier or serial output to detect DUT power off Change-type: minor Signed-off-by: Ryan Cooke --- lib/flashing/README.md | 9 +++ lib/flashing/index.ts | 100 +----------------------- lib/flashing/powerDetection/ethernet.ts | 67 ++++++++++++++++ lib/flashing/powerDetection/index.ts | 15 ++++ lib/flashing/powerDetection/serial.ts | 37 +++++++++ package-lock.json | 50 ++++++++++-- package.json | 1 + 7 files changed, 177 insertions(+), 102 deletions(-) create mode 100644 lib/flashing/powerDetection/ethernet.ts create mode 100644 lib/flashing/powerDetection/index.ts create mode 100644 lib/flashing/powerDetection/serial.ts diff --git a/lib/flashing/README.md b/lib/flashing/README.md index d622105..b00e8cb 100644 --- a/lib/flashing/README.md +++ b/lib/flashing/README.md @@ -34,6 +34,15 @@ There are multiple possibilities here: - If you do that, use `generic-flasher-boot-switch`. - if testing balenaOS - flash the internal storage of the device once manually. Then leave the switch in the internal storage position. Then connect it to the autokit. Future boots, the device will automatically boot from a flasher image on the SD card if present, or internal storage otherwise. This method requires no automated boot switch toggling, but may be weak for testing BSP updates +#### Power of detection for flasher images + +There are currently 2 ways to detect that a device running the flasher image has powered down after internal flashing: + +1. `ethernet`: (default) The ethernet carrier signal is used - the autokit will use the interface configured via the `WIRED_IF` env variable. `POWER_OFF_TIMEOUT` can be used to control the number of cycles to wait and check the signal. +2. `serial`: The serial output of the DUT is monitored for a message `reboot: Power down` , configurable via the `POWER_OFF_MESSAGE` env variable. The interface defined via the `DEV_SERIAL` will be used, and this requires the `ftdi` serial implementation to be used. `POWER_OFF_TIMEOUT` can be used to set a timeout in ms (default 5 mins). + +The method is selectable via `POWER_OFF_SELECTOR`, with `ethernet` or `serial` + ### USB-BOOT / raspberry pi compute module devices (CM3/CM4) For raspberry pi compute module devices, the autokit can bring them up into mass storage mode then write the OS image. diff --git a/lib/flashing/index.ts b/lib/flashing/index.ts index b038086..e251219 100644 --- a/lib/flashing/index.ts +++ b/lib/flashing/index.ts @@ -6,6 +6,7 @@ import * as sdk from 'etcher-sdk'; import * as fs from 'fs/promises'; import { BlockDeviceAdapter } from 'etcher-sdk/build/scanner/adapters'; import { Autokit } from '../'; +import { waitForPowerOff } from './powerDetection'; /** * Flash an image to a disk - this is the low level function used to flash a disk (SD card, USD storage device etc) @@ -129,22 +130,6 @@ async function flashSD(filename: string, autoKit: Autokit){ } -/** - * Checks whether the DUT is powered using Ethernet carrier detection - **/ -async function checkDutPower(autoKit:Autokit) { - const [stdout, _stderr] = await exec(`cat /sys/class/net/${autoKit.network.wiredIface}/carrier`); - const file = stdout.toString(); - if (file.includes('1')) { - console.log(`DUT is currently On`); - return true; - } else { - console.log(`DUT is currently Off`); - return false; - } -} - - const KEY_DELAY = Number(process.env.KEY_DELAY) || 500; async function keyboardSequence(autoKit: Autokit, keyboard: [string]){ for(let key of keyboard){ @@ -181,53 +166,8 @@ async function flashFlasher(filename: string, autoKit: Autokit, jumper: boolean, await autoKit.power.on(); - + await waitForPowerOff(autoKit); - // dut will now internally flash - need to wait until we detect DUT has powered off - // can be done through ethernet carrier signal, or through current measurement (or something else...) - // FOR NOW: use the network - // check if the DUT is on first - let dutOn = false; - while (!dutOn) { - console.log(`waiting for DUT to be on`); - dutOn = await checkDutPower(autoKit); - await delay(1000 * 5); // 5 seconds between checks - } - // once we confirmed the DUT is on, we wait for it to power down again, which signals the flashing has finished - // wait initially for 60s and then every 10s before checking if the board performed a shutdown after flashing the internal storage - const POLL_INTERVAL = 1000; // 1 second - const POLL_TRIES = 20; // 20 tries - const TIMEOUT_COUNT = 30; - let attempt = 0; - await delay(1000 * 60); - while (dutOn) { - await delay(1000 * 10); // 10 seconds between checks - console.log(`waiting for DUT to be off`); - dutOn = await checkDutPower(autoKit); - // occasionally the DUT might appear to be powered down, but it isn't - we want to confirm that the DUT has stayed off for an interval of time - if (!dutOn) { - let offCount = 0; - console.log(`detected DUT has powered off - confirming...`); - for (let tries = 0; tries < POLL_TRIES; tries++) { - await delay(POLL_INTERVAL); - dutOn = await checkDutPower(autoKit); - if (!dutOn) { - offCount += 1; - } - } - console.log( - `DUT stayted off for ${offCount} checks, expected: ${POLL_TRIES}`, - ); - if (offCount !== POLL_TRIES) { - // if the DUT didn't stay off, then we must try the loop again - dutOn = true; - } - } - attempt += 1; - if (attempt === TIMEOUT_COUNT){ - throw new Error(`Timed out while trying to flash internal storage!!`) - } - } console.log('Internally flashed - powering off DUT'); // power off and toggle mux. await delay(1000*10); @@ -527,41 +467,7 @@ async function flashJetson(filename: string, autoKit: Autokit, deviceType: strin if(nvme){ // wait for jetson to power off - const POLL_INTERVAL = 1000; // 1 second - const POLL_TRIES = 20; // 20 tries - const TIMEOUT_COUNT = 30000; - let attempt = 0; - let dutOn = true; - await delay(1000 * 60); - while (dutOn) { - await delay(1000 * 10); // 10 seconds between checks - console.log(`waiting for DUT to be off`); - dutOn = await checkDutPower(autoKit); - // occasionally the DUT might appear to be powered down, but it isn't - we want to confirm that the DUT has stayed off for an interval of time - if (!dutOn) { - let offCount = 0; - console.log(`detected DUT has powered off - confirming...`); - for (let tries = 0; tries < POLL_TRIES; tries++) { - await delay(POLL_INTERVAL); - dutOn = await checkDutPower(autoKit); - if (!dutOn) { - offCount += 1; - } - } - console.log( - `DUT stayted off for ${offCount} checks, expected: ${POLL_TRIES}`, - ); - if (offCount !== POLL_TRIES) { - // if the DUT didn't stay off, then we must try the loop again - dutOn = true; - } - } - attempt += 1; - if (attempt === TIMEOUT_COUNT){ - await autoKit.power.off(); - throw new Error(`Timed out while trying to flash internal storage!!. Powered off DUT.`) - } - } + await waitForPowerOff(autoKit); console.log('Internally flashed - powering off DUT'); } diff --git a/lib/flashing/powerDetection/ethernet.ts b/lib/flashing/powerDetection/ethernet.ts new file mode 100644 index 0000000..35dec87 --- /dev/null +++ b/lib/flashing/powerDetection/ethernet.ts @@ -0,0 +1,67 @@ +import { Autokit } from '../../'; +import { exec } from 'mz/child_process'; +import { delay } from 'bluebird'; + + +const TIMEOUT_COUNT = Number(process.env.POWER_OFF_TIMEOUT) || 30 + +/** + * Checks whether the DUT is powered using Ethernet carrier detection + **/ +async function checkDutPower(autoKit:Autokit) { + const [stdout, _stderr] = await exec(`cat /sys/class/net/${autoKit.network.wiredIface}/carrier`); + const file = stdout.toString(); + if (file.includes('1')) { + console.log(`DUT is currently On`); + return true; + } else { + console.log(`DUT is currently Off`); + return false; + } +} + +export async function waitForPowerOffEthernet(autoKit:Autokit):Promise{ + // dut will now internally flash - need to wait until we detect DUT has powered off + // FOR NOW: use the network + // check if the DUT is on first + let dutOn = false; + while (!dutOn) { + console.log(`waiting for DUT to be on`); + dutOn = await checkDutPower(autoKit); + await delay(1000 * 5); // 5 seconds between checks + } + + const POLL_INTERVAL = 1000; // 1 second + const POLL_TRIES = 20; // 20 tries + let attempt = 0; + await delay(1000 * 60); + while (dutOn) { + await delay(1000 * 10); // 10 seconds between checks + console.log(`waiting for DUT to be off`); + dutOn = await checkDutPower(autoKit); + // occasionally the DUT might appear to be powered down, but it isn't - we want to confirm that the DUT has stayed off for an interval of time + if (!dutOn) { + let offCount = 0; + console.log(`detected DUT has powered off - confirming...`); + for (let tries = 0; tries < POLL_TRIES; tries++) { + await delay(POLL_INTERVAL); + dutOn = await checkDutPower(autoKit); + if (!dutOn) { + offCount += 1; + } + } + console.log( + `DUT stayed off for ${offCount} checks, expected: ${POLL_TRIES}`, + ); + if (offCount !== POLL_TRIES) { + // if the DUT didn't stay off, then we must try the loop again + dutOn = true; + } + } + attempt += 1; + if (attempt === TIMEOUT_COUNT){ + await autoKit.power.off(); + throw new Error(`Timed out while trying to flash internal storage!!. Powered off DUT.`) + } + } +} \ No newline at end of file diff --git a/lib/flashing/powerDetection/index.ts b/lib/flashing/powerDetection/index.ts new file mode 100644 index 0000000..5e44d45 --- /dev/null +++ b/lib/flashing/powerDetection/index.ts @@ -0,0 +1,15 @@ +import { Autokit } from "../.."; +import { waitForPowerOffEthernet } from "./ethernet"; +import { waitForPowerOffSerial } from "./serial"; + +const powerOffSelector = process.env.POWER_OFF_SELECTOR || 'ethernet' + +const powerOffFunctions: {[key: string]: (autoKit: Autokit) => Promise } = { + ethernet: waitForPowerOffEthernet, + serial: waitForPowerOffSerial, +}; + +const waitForPowerOff = powerOffFunctions[powerOffSelector]; + + +export { waitForPowerOff } \ No newline at end of file diff --git a/lib/flashing/powerDetection/serial.ts b/lib/flashing/powerDetection/serial.ts new file mode 100644 index 0000000..a5330be --- /dev/null +++ b/lib/flashing/powerDetection/serial.ts @@ -0,0 +1,37 @@ +import { Autokit } from '../../'; +import { ReadlineParser } from '@serialport/parser-readline'; +import { Readable } from 'serialport'; + +const powerOffMessage = process.env.POWER_OFF_MESSAGE || 'reboot: Power down' +const timeout = Number(process.env.POWER_OFF_TIMEOUT) || 1000*60*5; + +/** + * Checks whether the DUT has powered down by checking for a serial message + **/ +export async function waitForPowerOffSerial(autoKit:Autokit):Promise { + const serialport = await autoKit.serial.open(); + + if(serialport !== undefined){ + return new Promise((resolve, reject) => { + + let timer = setTimeout(async () => { + await autoKit.serial.close(); + reject(`Timed out while waiting for power down message over serial!`); + }, timeout) + + // Examine each line of the serial output from the DUT as it comes in + const parser = serialport.pipe(new ReadlineParser({ delimiter: '\n' })); + parser.on('data', async(data:string) => { + console.log(`Serial line: ${data.toString()}`); + if(data.toString().includes(powerOffMessage)){ + console.log(`### Detected power off message ###`) + await autoKit.power.off(); + await autoKit.serial.close(); + clearTimeout(timer); + resolve(); + } + }) + }) + + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 1e2acb5..fff34e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "Apache-2.0", "dependencies": { "@balena/usbrelay": "^0.1.4", + "@serialport/parser-readline": "^12.0.0", "bluebird": "^3.7.2", "bluebird-retry": "^0.11.0", "dbus-next": "^0.9.0", @@ -805,6 +806,20 @@ "url": "https://opencollective.com/serialport/donate" } }, + "node_modules/@serialport/bindings/node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, "node_modules/@serialport/parser-byte-length": { "version": "9.2.4", "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", @@ -850,14 +865,25 @@ } }, "node_modules/@serialport/parser-readline": { - "version": "9.2.4", - "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", - "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-12.0.0.tgz", + "integrity": "sha512-O7cywCWC8PiOMvo/gglEBfAkLjp/SENEML46BXDykfKP5mTPM46XMaX1L0waWU6DXJpBgjaL7+yX6VriVPbN4w==", "dependencies": { - "@serialport/parser-delimiter": "9.2.4" + "@serialport/parser-delimiter": "12.0.0" }, "engines": { - "node": ">=10.0.0" + "node": ">=12.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline/node_modules/@serialport/parser-delimiter": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-12.0.0.tgz", + "integrity": "sha512-gu26tVt5lQoybhorLTPsH2j2LnX3AOP2x/34+DUSTNaUTzu2fBXw+isVjQJpUBFWu6aeQRZw5bJol5X9Gxjblw==", + "engines": { + "node": ">=12.0.0" }, "funding": { "url": "https://opencollective.com/serialport/donate" @@ -3227,6 +3253,20 @@ "url": "https://opencollective.com/serialport/donate" } }, + "node_modules/serialport/node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", diff --git a/package.json b/package.json index 1d5e782..2f4b447 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "license": "Apache-2.0", "dependencies": { "@balena/usbrelay": "^0.1.4", + "@serialport/parser-readline": "^12.0.0", "bluebird": "^3.7.2", "bluebird-retry": "^0.11.0", "dbus-next": "^0.9.0", From 2ece30737471a62debdf408c1373b69bc325397b Mon Sep 17 00:00:00 2001 From: Ryan Cooke Date: Mon, 18 Nov 2024 13:12:34 +0000 Subject: [PATCH 3/4] power: add override for tx2 device type This adds a subclass for use with the tx2 device type derived from autokitRelay() - it modifies the on and off functions to use the tx2 button press sequence instead Change-type: patch Signed-off-by: Ryan Cooke --- lib/features/power/README.md | 1 + .../implementations/autokit-relay/README.md | 3 +- .../implementations/autokit-relay/index.ts | 8 +- .../autokit-relay/jetson-tx2.ts | 80 +++++++++++++++++++ lib/features/power/index.ts | 2 + 5 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 lib/features/power/implementations/autokit-relay/jetson-tx2.ts diff --git a/lib/features/power/README.md b/lib/features/power/README.md index bfc39c3..b53e22a 100644 --- a/lib/features/power/README.md +++ b/lib/features/power/README.md @@ -6,4 +6,5 @@ For controlling the power on/off state of the DUT. - `autokitRelay` - `crelay` +- `jetsonTx2` (specifically for use with jetson Tx2 dev kit) - `dummyPower`: for use when no device is connected \ No newline at end of file diff --git a/lib/features/power/implementations/autokit-relay/README.md b/lib/features/power/implementations/autokit-relay/README.md index 0f4ea9e..c7d18da 100644 --- a/lib/features/power/implementations/autokit-relay/README.md +++ b/lib/features/power/implementations/autokit-relay/README.md @@ -15,4 +15,5 @@ They used a HID interface and are controllable via: - `POWER_RELAY_SERIAL`: the serial of the relay. An example of how to obtain that is here: https://github.com/darrylb123/usbrelay?tab=readme-ov-file#usage - `POWER_RELAY_NUM`: for specifying which channel of the relay is being used for the power control of the DUT in the case of multiple channels being on the relay. Default is `0` which leads to all channels being toggled - actual channel numbers start at `1` -- `USB_RELAY_CONN`: `NO` or `NC` - for selecting if the normally open or closed configuration is used - default is `NO` and recommended \ No newline at end of file +- `USB_RELAY_CONN`: `NO` or `NC` - for selecting if the normally open or closed configuration is used - default is `NO` and recommended +- `GPIO_POWER_DET` : (Tx2 specific) - for selecting the PGIO pin to be used for power state detection \ No newline at end of file diff --git a/lib/features/power/implementations/autokit-relay/index.ts b/lib/features/power/implementations/autokit-relay/index.ts index ab4c598..c8d6443 100644 --- a/lib/features/power/implementations/autokit-relay/index.ts +++ b/lib/features/power/implementations/autokit-relay/index.ts @@ -3,10 +3,10 @@ const USBRelay = require("@balena/usbrelay"); export class AutokitRelay implements Power { - private relayId: string - private powerRelay: any - private conn: boolean - private relayNum: number + public relayId: string + public powerRelay: any + public conn: boolean + public relayNum: number constructor(){ this.relayId = process.env.POWER_RELAY_SERIAL || 'HURTM' this.relayNum = Number(process.env.POWER_RELAY_NUM || '0') diff --git a/lib/features/power/implementations/autokit-relay/jetson-tx2.ts b/lib/features/power/implementations/autokit-relay/jetson-tx2.ts new file mode 100644 index 0000000..82d8fac --- /dev/null +++ b/lib/features/power/implementations/autokit-relay/jetson-tx2.ts @@ -0,0 +1,80 @@ +import { delay } from 'bluebird'; +import { AutokitRelay } from "./"; +import { exec } from 'mz/child_process'; + +// Device specific override for Tx2 power on / off sequencing +// Assumes this USB relay is connected to J6, NO +export class JetsonTx2Power extends AutokitRelay { + // Only way of determining Tx2 power state is via GPIO J21.1 + public gpio: string; + + constructor(){ + super(); + this.gpio = process.env.GPIO_POWER_DET || '112' + } + + async setup(){ + await super.setup(); + // Setup GPIO pin to detect power state + await exec(`echo ${this.gpio} > /sys/class/gpio/export || true`).catch(() => { + console.log(`Failed to export gpio for checking DUT power`); + }); + await exec(`echo in > /sys/class/gpio/gpio${this.gpio}/direction || true`).catch(() => { + console.log(`Failed to set gpio${this.gpio} as input`); + }); + await delay(500); + } + + private async checkDutPower() { + const [stdout, stderr] = await exec(`cat /sys/class/gpio/gpio${this.gpio}/value`); + console.log(stderr); + const file = stdout.toString(); + + if (file.includes('1')) { + console.log(`checkDutPower() - DUT is currently On`); + return true; + } else { + console.log(`checkDutPower() - DUT is currently Off`); + return false; + } + } + + // Power on the DUT + async on(): Promise { + // Trigger power on via a short button press - by toggling on, waiting, then toggling off + console.log(`Triggering TX2 power on sequence...`); + await delay(1000); + await super.on(); + await delay(3000); + await super.off(); + await delay(3000); + console.log(`Triggered power on sequence on TX2!`); + } + + // Power off the DUT + async off(): Promise { + // Trigger power off via a short button press - by toggling on, waiting, then toggling off + // If the DUT is already off, this will actually power the board back on - leading to potentially strange states during the provisioning + console.log(`powerOff - Will turn off TX2`); + const dutIsOn = await this.checkDutPower(); + if (dutIsOn) { + console.log('TX2 is booted, trigger normal shutdown'); + // Simulate short press on the power button + await delay(1000); + await super.on(); + await delay(10 * 1000); + await super.off() + + console.log(`Triggered power off sequence on TX2`); + await delay(1000); + + /* Ensure device is off */ + const dutIsOn = await this.checkDutPower(); + if (dutIsOn) { + console.log('WARN: Triggered force shutdown but TX2 did not power off'); + } + } else { + console.log('TX2 is not booted, no power toggle needed'); + } + } +} diff --git a/lib/features/power/index.ts b/lib/features/power/index.ts index 71991ff..457f724 100644 --- a/lib/features/power/index.ts +++ b/lib/features/power/index.ts @@ -1,11 +1,13 @@ import { AutokitRelay } from "./implementations/autokit-relay"; import { DummyPower } from "./implementations/dummy-power"; import { Crelay } from "./implementations/crelay"; +import { JetsonTx2Power } from "./implementations/autokit-relay/jetson-tx2"; const powerImplementations: {[key: string]: Type } = { autokitRelay: AutokitRelay, dummyPower: DummyPower, crelay: Crelay, + jetsonTx2: JetsonTx2Power }; export { powerImplementations } \ No newline at end of file From 2c25b18c249639ae1aeae2f5d0637fefa91480db Mon Sep 17 00:00:00 2001 From: Ryan Cooke Date: Tue, 19 Nov 2024 16:44:57 +0000 Subject: [PATCH 4/4] power: jetsonTx2: use eth carrier instead of GPIO for power state Change-type: patch Signed-off-by: Ryan Cooke --- .../autokit-relay/jetson-tx2.ts | 40 ++++++------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/lib/features/power/implementations/autokit-relay/jetson-tx2.ts b/lib/features/power/implementations/autokit-relay/jetson-tx2.ts index 82d8fac..464aa96 100644 --- a/lib/features/power/implementations/autokit-relay/jetson-tx2.ts +++ b/lib/features/power/implementations/autokit-relay/jetson-tx2.ts @@ -5,38 +5,24 @@ import { exec } from 'mz/child_process'; // Device specific override for Tx2 power on / off sequencing // Assumes this USB relay is connected to J6, NO export class JetsonTx2Power extends AutokitRelay { - // Only way of determining Tx2 power state is via GPIO J21.1 - public gpio: string; + // Only way of determining Tx2 power state is checking the ethernet carrier state + public wiredIface: string; constructor(){ super(); - this.gpio = process.env.GPIO_POWER_DET || '112' + this.wiredIface = process.env.WIRED_IF || 'eth1'; } - async setup(){ - await super.setup(); - // Setup GPIO pin to detect power state - await exec(`echo ${this.gpio} > /sys/class/gpio/export || true`).catch(() => { - console.log(`Failed to export gpio for checking DUT power`); - }); - await exec(`echo in > /sys/class/gpio/gpio${this.gpio}/direction || true`).catch(() => { - console.log(`Failed to set gpio${this.gpio} as input`); - }); - await delay(500); - } - - private async checkDutPower() { - const [stdout, stderr] = await exec(`cat /sys/class/gpio/gpio${this.gpio}/value`); - console.log(stderr); - const file = stdout.toString(); - - if (file.includes('1')) { - console.log(`checkDutPower() - DUT is currently On`); - return true; - } else { - console.log(`checkDutPower() - DUT is currently Off`); - return false; - } + async checkDutPower() { + const [stdout, _stderr] = await exec(`cat /sys/class/net/${this.wiredIface}/carrier`); + const file = stdout.toString(); + if (file.includes('1')) { + console.log(`DUT is currently On`); + return true; + } else { + console.log(`DUT is currently Off`); + return false; + } } // Power on the DUT