homebridge-smartsystem
Version:
SmartServer (Proxy Websockets to TCP sockets, Smappee MQTT, Duotecno IP Nodes, Homekit interface)
174 lines (140 loc) • 4.14 kB
text/typescript
import * as sgpio from 'rpi-gpio';
import { debug, LogLevel, logSettings } from "../duotecno/logger";
const gpio = sgpio.promise;
const s3v3 = 1; // pin 1
const sGnd = 3; // pin 3
const sUp = 5; // pin 29
const sDown = 6; // pin 31
const sSelect = 16; // pin 36
const sStop = 26; // pin 37 -- make 0 not to use "stop"
const sScreen1 = 25; // pin 22
const sScreen2 = 24; // pin 18
const sScreen3 = 23; // pin 16
const sScreen4 = 22; // pin 15
const kWaitPush = 150;
const kWaitStable = 200;
let init: boolean;
let busy: boolean;
async function mS(nr: number) {
return new Promise(resolve => setTimeout(resolve, nr));
}
async function setup() {
logSettings["somfy"] = LogLevel.debug;
// use real names (MODE_BCM) or pin numbers(MODE_RPI)
sgpio.setMode(sgpio.MODE_BCM);
// set for output
await gpio.setup(sSelect, gpio.DIR_OUT);
await gpio.write(sSelect, true);
await gpio.setup(sUp, gpio.DIR_OUT);
await gpio.write(sUp, true);
await gpio.setup(sDown, gpio.DIR_OUT);
await gpio.write(sDown, true);
if (sStop) {
await gpio.setup(sStop, gpio.DIR_OUT);
await gpio.write(sStop, true);
}
// set for input active low
await gpio.setup(sScreen1, gpio.DIR_IN);
await gpio.setup(sScreen2, gpio.DIR_IN);
await gpio.setup(sScreen3, gpio.DIR_IN);
await gpio.setup(sScreen4, gpio.DIR_IN);
}
async function toggle(pin) {
await gpio.write(pin, false);
await mS(kWaitPush);
await gpio.write(pin, true);
await mS(kWaitStable);
}
async function selected(screen: number): Promise<boolean> {
const screens = [false,
! await gpio.read(sScreen1),
! await gpio.read(sScreen2),
! await gpio.read(sScreen3),
! await gpio.read(sScreen4)];
screens[0] = screens[1] && screens[2] && screens[3] && screens[4];
if (screens[0]) {
screens[1] = screens[2] = screens[3] = screens[4] = false;
}
debug("somfy", "selected screen: " + screens[0] +" "+ screens[1] +" "+ screens[2] +" "+ screens[3] +" "+ screens[4]+ " <- " + screen + "=" + screens[screen]);
return screens[screen];
}
async function select(screen: number): Promise<boolean> {
debug("somfy", "try to select screen " + screen);
let i = 0;
do {
await toggle(sSelect);
if (await selected(screen)) return true;
i++;
} while (i < 5);
// give up after 5 tries
debug("somfy", "Error: couldn't select screen " + screen);
return false;
}
async function waitBusy() {
// wait the average selection time
const kWaitingTime = (kWaitStable+kWaitPush) * 2.5;
let nr = 0;
while (busy) {
nr++;
debug("somfy", "waiting for busy flag - " + Math.round(nr*kWaitingTime) + "mSec")
await mS(kWaitingTime);
}
busy = true;
}
export async function down(screen: number): Promise<boolean> {
debug("somfy", "down " + screen + ((init) ? "" : " - test mode"));
if (!init) return true;
await waitBusy();
if (await select(screen)) {
await toggle(sDown);
busy = false;
return true;
}
busy = false;
return false;
}
export async function up(screen: number): Promise<boolean> {
debug("somfy", "up " + screen + ((init) ? "" : " - test mode"));
if (!init) return true;
await waitBusy();
if (await select(screen)) {
await toggle(sUp);
busy = false;
return true;
}
busy = false;
return false;
}
export async function stop(screen: number): Promise<boolean> {
debug("somfy", "stop " + screen + ((init) ? "" : " - test mode"));
if (!init) return true;
await waitBusy();
if (sStop) {
if (await select(screen)) {
await toggle(sStop);
busy = false;
return true;
}
busy = false;
return false;
} else {
busy = false;
return true;
}
}
// async function testing() {
// await setup();
// await down(3);
// await up(2);
// }
busy = true;
setup().then(() => {
debug("somfy", "gpio package initialized");
init = true;
busy = false;
}).catch((e) => {
debug("somfy", "gpio package not initialized");
if ((e.code != "EACCES") && (e.code != "ENOENT")) debug("somfy", e);
init = false;
busy = false;
});