src.nth.io/

summaryrefslogtreecommitdiff
path: root/npmjs-package/src/door.js
blob: 24978d0134851c4e61a496e6f84d8d4ca5e97fe6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
const hap = require("hap-nodejs");
const pysh = require("python-shell");

const Accessory = hap.Accessory;
const Characteristic = hap.Characteristic;
const CharacteristicEventTypes = hap.CharacteristicEventTypes;
const AccessoryEventTypes = hap.AccessoryEventTypes;
const Service = hap.Service;
const uuid = hap.uuid;

const accessoryUuid = hap.uuid.generate("hap.accessories.doorbell-lock");
const accessory = new Accessory("Doorbell and Lock", accessoryUuid);

const doorbellService = new Service.Doorbell("Doorbell");
const lockService = new Service.LockMechanism("Lock");

const lockTargetStateCharacteristic = lockService.getCharacteristic(Characteristic.LockTargetState);
const lockCurrentStateCharacteristic = lockService.getCharacteristic(Characteristic.LockCurrentState);

const doorbellSwitchCharacteristic = doorbellService.getCharacteristic(Characteristic.ProgrammableSwitchEvent);

function Door() {
    this.lockTimeout = 10000; // milliseconds - 10 sec

    this.pyshell = new pysh.PythonShell("doord.py", {
        mode: "text",
        pythonPath: "/usr/bin/python3",
        pythonOptions: ["-u"],
        scriptPath: "python/"
    });

    this.lock = () => {
        console.log("locking door");
        this.pyshell.send("lock");
    };

    this.unlock = () => {
        console.log("unlocking door");
        this.pyshell.send("unlock");
    };

    this.identify = () => { console.log("identify door"); };

    this.listenDoorbell = (doorbellOnCallback, doorbellOffCallback) => {
        this.pyshell.on("message", (message) => {
            console.log(message);
            switch(message) {
            case "doorbell on":
                doorbellOnCallback();
                break;
            case "doorbell off":
                doorbellOffCallback();
                break;
            }
        });
    };
}

const door = new Door();

function setDoorTargetState(value) {
    switch(value) {
    case Characteristic.LockTargetState.UNSECURED:
        unlockDoor();
        break;
    case Characteristic.LockTargetState.SECURED:
        lockDoor();
        break;
    }
}

function unlockDoor() {
    door.unlock();
    lockCurrentStateCharacteristic.setValue(Characteristic.LockCurrentState.UNSECURED);
    scheduleUnlockTimeout();
}

function lockDoor() {
    door.lock();
    lockCurrentStateCharacteristic.setValue(Characteristic.LockCurrentState.SECURED);
}

function scheduleUnlockTimeout() {
    setTimeout(() => {
        console.log("unlock timeout door");
        lockTargetStateCharacteristic.setValue(Characteristic.LockTargetState.SECURED);
    }, door.lockTimeout);
}

door.listenDoorbell(
    () => {
        doorbellSwitchCharacteristic.setValue(Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS);
    },
    () => {}
);

// set initial state
lockTargetStateCharacteristic.setValue(Characteristic.LockTargetState.SECURED);
lockCurrentStateCharacteristic.setValue(Characteristic.LockCurrentState.SECURED);
lockTargetStateCharacteristic.on(CharacteristicEventTypes.SET, (value, callback) => {
    setDoorTargetState(value);
    callback();
});

accessory.on(AccessoryEventTypes.IDENTIFY, (paired, callback) => {
    door.identify();
    callback();
});

accessory.addService(doorbellService);
accessory.addService(lockService);

// pseudo-services
accessory.addService(Service.CameraRTPStreamManagement, "Pseudo-Camera");
accessory.addService(Service.Speaker, "Pseudo-Speaker");
accessory.addService(Service.Microphone, "Pseudo-Microphone");

accessory.getService(Service.AccessoryInformation)
    .setCharacteristic(Characteristic.Manufacturer, "Raspberry Pi")
    .setCharacteristic(Characteristic.Model, "Zero W")
    .setCharacteristic(Characteristic.SerialNumber, "A1S2NASF88EW");

accessory.publish({
  username: "C1:5D:3A:EA:54:AB",
  pincode: "031-45-154",
  category: hap.Categories.DOOR_LOCK
});

console.log("Accessory initialized");