Skip to content

Commit

Permalink
Fix Contact Sensor, updateStatusIcon
Browse files Browse the repository at this point in the history
  • Loading branch information
Claudio Chimera authored and Claudio Chimera committed Oct 14, 2021
1 parent fe83166 commit 399ab61
Show file tree
Hide file tree
Showing 3 changed files with 370 additions and 96 deletions.
60 changes: 47 additions & 13 deletions alexa/alexa-adapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ module.exports = function (RED) {
const RULE_TRIGGER = 'RULE_TRIGGER';
const VOICE_INTERACTION = 'VOICE_INTERACTION';

const PROPERTIES_MAPPING = {
motionDetectionState: ['Alexa.MotionSensor', 'detectionState'],
contactDetectionState: ['Alexa.ContactSensor', 'detectionState']
};

class AlexaAdapterNode {
constructor(config) {
RED.nodes.createNode(this, config);
Expand Down Expand Up @@ -659,8 +664,8 @@ module.exports = function (RED) {
if (node.config.verbose) node._debug(" CCHI directive " + namespace + " " + name + " " + JSON.stringify(req.body.directive.payload));
try {
let cmd_res = {};
const changed_propertie_names = node.devices[endpointId].execDirective(header, req.body.directive.payload, cmd_res);
if (changed_propertie_names !== undefined) {
const changed_property_names = node.devices[endpointId].execDirective(header, req.body.directive.payload, cmd_res);
if (changed_property_names !== undefined) {
node.get_access_token('evn')
.then(access_token => {
const r_namespace = cmd_res['namespace'];
Expand All @@ -676,7 +681,7 @@ module.exports = function (RED) {
// if (node.config.verbose) node._debug("CCHI report_state async response NOT SENT YET " + JSON.stringify(report_state));
if (r_name != 'DeferredResponse' && r_name != 'ErrorResponse' && r_namespace != "Alexa.SceneController") {
process.nextTick(() => {
node.send_change_report(endpointId, changed_propertie_names, VOICE_INTERACTION, cmd_res).then(() => { });
node.send_change_report(endpointId, changed_property_names, VOICE_INTERACTION, cmd_res).then(() => { });
});
}
})
Expand Down Expand Up @@ -1254,22 +1259,22 @@ module.exports = function (RED) {
//
//
//
send_change_report(endpointId, changed_propertie_names, reason, cmd_res, namespace, name) {
send_change_report(endpointId, changed_property_names, reason, cmd_res, namespace, name) {
// https://github.com/alexa/alexa-smarthome/blob/master/sample_async/python/sample_async.py
// https://developer.amazon.com/en-US/docs/alexa/smarthome/state-reporting-for-a-smart-home-skill.html
// https://developer.amazon.com/en-US/docs/alexa/smarthome/send-events-to-the-alexa-event-gateway.html
var node = this;
return new Promise((resolve, reject) => {
if (node.config.verbose) node._debug('send_change_report ' + endpointId);
if (changed_propertie_names === undefined) {
changed_propertie_names = [];
if (changed_property_names === undefined) {
changed_property_names = [];
}
else if (typeof changed_propertie_names === 'string') {
changed_propertie_names = [changed_propertie_names];
else if (typeof changed_property_names === 'string') {
changed_property_names = [changed_property_names];
}
node.get_access_token('evn')
.then(access_token => {
let state = node.get_change_report(endpointId, namespace, name, undefined, changed_propertie_names, reason);
let state = node.get_change_report(endpointId, namespace, name, undefined, changed_property_names, reason);
node.objectMerge(state, cmd_res);
if (node.config.verbose) node._debug('send_change_report state ' + JSON.stringify(state));
if (node.config.verbose) node._debug('send_change_report to event_endpoint ' + node.config.event_endpoint);
Expand Down Expand Up @@ -1508,17 +1513,46 @@ module.exports = function (RED) {
//
//
//
get_change_report(endpointId, namespace, name, messageId, changed_propertie_names, reason) {
get_mapped_property(namespace, name) {
Object.keys(PROPERTIES_MAPPING).forEach(i_name => {
if (PROPERTIES_MAPPING[i_name][1] === name && PROPERTIES_MAPPING[i_name][0] === namespace) {
name = i_name;
}
});
return name;
}

//
//
//
//
is_changed_property(name, namespace, changed_property_names) {
if (changed_property_names.includes(name)) {
return true;
}
let res = false;
Object.keys(PROPERTIES_MAPPING).forEach(key => {
if (PROPERTIES_MAPPING[key][1] === name && PROPERTIES_MAPPING[key][0] === namespace && changed_property_names.includes(key)) {
res = true;
}
});
return res;
}
//
//
//
//
get_change_report(endpointId, namespace, name, messageId, changed_property_names, reason) {
var node = this;
let changed_properties = [];
let unchanged_properties = [];
let payload = {};
const oauth2_bearer_token = node.tokens.evn.access_token;
const properties = node.devices[endpointId].getProperties();
if (node.config.verbose) node._debug('endpointId ' + endpointId + ' properties ' + JSON.stringify(properties));
if (changed_propertie_names && changed_propertie_names.length > 0) {
if (node.config.verbose) node._debug('get_change_report endpointId ' + endpointId + ' properties ' + JSON.stringify(properties));
if (changed_property_names.length > 0) {
properties.forEach(property => {
if (changed_propertie_names && changed_propertie_names.includes(property.name)) {
if (node.is_changed_property(property.name, property.namespace, changed_property_names)) {
changed_properties.push(property);
} else {
unchanged_properties.push(property);
Expand Down
109 changes: 94 additions & 15 deletions alexa/alexa-device.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ module.exports = function (RED) {
if (node.isVerbose()) node._debug("(on-close) " + node.config.name);
node.onClose(removed, done);
});
node.updateStatusIcon();
}

//
Expand Down Expand Up @@ -277,9 +278,9 @@ module.exports = function (RED) {
if (node.isVerbose()) node._debug("Alexa.ColorController");
node.addCapability("Alexa.ColorController", {
color: {
"hue": 350.5,
"saturation": 0.7138,
"brightness": 0.6524
hue: 350.5,
saturation: 0.7138,
brightness: 0.6524
}
});
}
Expand All @@ -299,8 +300,6 @@ module.exports = function (RED) {
if (node.isVerbose()) node._debug("Alexa.ContactSensor");
node.addCapability("Alexa.ContactSensor", {
detectionState: 'NOT_DETECTED'
}, undefined, {
detectionState: 'contactDetectionState'
});
}

Expand Down Expand Up @@ -491,8 +490,6 @@ module.exports = function (RED) {
if (node.isVerbose()) node._debug("Alexa.MotionSensor");
node.addCapability("Alexa.MotionSensor", {
detectionState: 'NOT_DETECTED' // DETECTED
}, undefined, {
detectionState: 'motionDetectionState'
});
}
// PercentageController
Expand Down Expand Up @@ -692,20 +689,19 @@ module.exports = function (RED) {
//
//
//
getCapability(iface, properties_val, properties_map) {
getCapability(iface, properties_val) {
var node = this;
let capability = {
type: "AlexaInterface",
interface: iface,
version: "3",
};
if (properties_val) {
if (typeof properties_map === 'undefined') {
properties_map = {};
}
let supported = [];
Object.keys(properties_val).forEach(key => {
node.state[properties_map[key] || key] = properties_val[key];
const mapped_key = node.alexa.get_mapped_property(iface, key);
console.log("CCHI TOOOOOOOOOOOOOOOOOOOOOOOOOOOOO TODO mapped_key " + iface + ' ' + key + " . " + mapped_key)
node.state[mapped_key] = properties_val[key];
supported.push({
name: key
});
Expand All @@ -723,9 +719,9 @@ module.exports = function (RED) {
//
//
//
addCapability(iface, properties_val, attributes, properties_map) {
addCapability(iface, properties_val, attributes) {
var node = this;
let capability = node.getCapability(iface, properties_val, properties_map);
let capability = node.getCapability(iface, properties_val);
if (attributes !== undefined) {
Object.assign(capability, attributes);
}
Expand All @@ -744,6 +740,7 @@ module.exports = function (RED) {
const name = header['name']
if (node.isVerbose()) node._debug("execDirective state before " + name + "/" + namespace + " " + JSON.stringify(node.state));
let modified = undefined;
let send_state_in_out = true;
let event_payload = {};
let res_payload = {};
cmd_res['event'] = {
Expand Down Expand Up @@ -922,6 +919,7 @@ module.exports = function (RED) {
cmd_res["name"] = "DeferredResponse";
event_payload['estimatedDeferralInSeconds'] = 15;
modified = [];
send_state_in_out = false;
process.nextTick(() => {
if (node.isVerbose()) node._debug("execDirective send_change_report");
// TODO manage response
Expand All @@ -931,6 +929,7 @@ module.exports = function (RED) {
modified = node.setValues({
powerState: 'ON'
}, node.state);
node.sendState(modified, payload, namespace, name);
node.alexa.send_change_report(node.id, [], "VOICE_INTERACTION", {
event: {
header: {
Expand Down Expand Up @@ -1122,7 +1121,7 @@ module.exports = function (RED) {
}


if (modified !== undefined) {
if (send_state_in_out && modified !== undefined) {
node.sendState(modified, payload, namespace, name);
}

Expand Down Expand Up @@ -1349,6 +1348,85 @@ module.exports = function (RED) {
return properties;
}

//
//
//
//
updateStatusIcon() {
const node = this;
let text = '';
let fill = 'blue';
let shape = 'dot';
if (node.state.powerState !== undefined) {
if (node.state.powerState === 'ON') {
text = 'ON';
fill = 'green';
} else {
text = 'OFF';
fill = 'red';
}
}
if (node.state.powerLevel !== undefined) {
text += " P: " + node.state.powerLevel;
}
if (node.state.brightness !== undefined) {
text += " bri: " + node.state.brightness;
}
if (node.state.colorTemperatureInKelvin !== undefined) {
text += ' temp: ' + node.state.colorTemperatureInKelvin;
}
if (node.state.color !== undefined) {
text += ' H: ' + node.state.color.hue +
' S: ' + node.state.color.saturation +
' B: ' + node.state.color.brightness;
}
if (node.state.lockState !== undefined) {
text += ' ' + node.state.lockState;
}
if (node.state.armState !== undefined) {
text += ' ' + node.state.armState;
}
if (node.state.percentage !== undefined) {
text += ' ' + node.state.percentage + "% ";
}
if (node.state.volume !== undefined) {
text += ' vol: ' + node.state.volume;
}
if (node.state.muted !== undefined && node.state.muted) {
text += ' M';
}
if (node.state.temperature !== undefined) {
text += ' T: ' + node.state.temperature.value;
}
if (node.state.targetSetpoint !== undefined) {
text += ' TS: ' + node.state.targetSetpoint.value;
}

if (node.state.lowerSetpoint !== undefined && node.state.upperSetpoint !== undefined) {
text += ' TS: [' + node.state.lowerSetpoint.value + ',' + node.state.upperSetpoint.value + ']';
}

if (node.state.motionDetectionState !== undefined) {
text += node.state.motionDetectionState === 'DETECTED' ? ' MOTION' : ' NO MOTION';
}

if (node.state.contactDetectionState !== undefined) {
text += node.state.contactDetectionState === 'DETECTED' ? ' CONTACT' : ' NO CONTACT';
}
if (node.state.connectivity !== undefined) {
if (node.state.connectivity === 'UNREACHABLE') {
fill = 'red';
} else if (fill !== 'red') {
fill = 'green';
}
}

if (!text) {
text = 'Unknown';
}
node.status({ fill: fill, shape: shape, text: text });
}

//
//
//
Expand Down Expand Up @@ -1422,6 +1500,7 @@ module.exports = function (RED) {
}
}
});
node.updateStatusIcon();
return differs;
}

Expand Down
Loading

0 comments on commit 399ab61

Please sign in to comment.