Skip to content

Commit

Permalink
config option to use nice zone names
Browse files Browse the repository at this point in the history
  • Loading branch information
noobydp committed May 17, 2020
1 parent 434d197 commit a47a0ab
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
| `manufacturer` _(optional)_ | Appears under "Manufacturer" for your AC accessory in the Home app |
| `model` _(optional)_ | Appears under "Model" for your AC accessory in the Home app |
| `fan` _(required)_ | List with fan speeds that can be set for your AC |
| `use_group_names` _(optional)_ | Use the display names from the Polyaire groups instead of generic zone names (Warning: changing this after setup will cause zones to appear twice) |

## Accessories

Expand Down
65 changes: 64 additions & 1 deletion api.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,25 @@ var net = require("net");
//
function AirtouchAPI(log) {
this.log = log;
this.zoneNames = { // setting default names in case the zone names are not found correctly and enable the feature to be turned off
"Zone 0": "0",
"Zone 1": "1",
"Zone 2": "2",
"Zone 3": "3",
"Zone 4": "4",
"Zone 5": "5",
"Zone 6": "6",
"Zone 7": "7",
"Zone 8": "8",
"Zone 9": "9",
"Zone 10": "10",
"Zone 11": "11",
"Zone 12": "12",
"Zone 13": "13",
"Zone 14": "14",
"Zone 15": "15",
"Zone 16": "16",
};
};

// messages have the data checksummed using modbus crc16
Expand All @@ -31,6 +50,17 @@ function crc16(buffer) {
return crc;
};

// need to convert hex into ascii text for zone and group names
function hex_to_ascii(str1)
{
var hex = str1.toString();
var str = '';
for (var n = 0; n < hex.length; n += 2) {
str += String.fromCharCode(parseInt(hex.substr(n, 2), 16));
}
return str;
}

// check if value is undefined, and replace it with a default value
function isNull(val, nullVal) {
return val === undefined ? nullVal : val;
Expand Down Expand Up @@ -60,6 +90,15 @@ AirtouchAPI.prototype.send = function(type, data) {
this.device.write(message);
};

AirtouchAPI.prototype.sendBufferDirect = function (dataBuffer) {
// assemble message
// let message = Buffer.from(data);
this.log("API | Message to send direct:");
this.log(dataBuffer);
// send message
this.device.write(dataBuffer);
}

// encode a message for AC command
AirtouchAPI.prototype.encode_ac_control = function(unit) {
let byte1 = isNull(unit.ac_unit_number, MAGIC.AC_UNIT_DEFAULT);
Expand Down Expand Up @@ -138,6 +177,15 @@ AirtouchAPI.prototype.GET_AC_STATUS = function() {
this.send(MAGIC.MSGTYPE_AC_STAT, data);
};

// send command to get full System details
AirtouchAPI.prototype.GET_SYS_DETAILS = function() {
// due to a bug, cannot send empty data
// so we send one byte of data
this.log("called get sys details");
let dataBuffer = Buffer.from(MAGIC.MSGDATA_SYS_DETAILS);
this.sendBufferDirect(dataBuffer);
};

// decode AC status information and send it to homebridge
AirtouchAPI.prototype.decode_ac_status = function(data) {
ac_status = [];
Expand Down Expand Up @@ -264,16 +312,28 @@ AirtouchAPI.prototype.decode_groups_status = function(data) {
this.emit("groups_status", groups_status);
};

// decode groups information and store it
AirtouchAPI.prototype.decode_sys_details = function(data) {
let strData = data.toString("hex");
for (i = 0; i < 15; i++) { //16 max group names
zoneName = hex_to_ascii(strData.substr(268 + i*16, 16)).replace(/[^\x20-\x7E]/g, '');
this.zoneNames["Zone " + i] = zoneName;
};
};

// connect to Airtouch Touchpad Controller socket on tcp port 9004
AirtouchAPI.prototype.connect = function(address) {
this.device = new net.Socket();
this.device.connect(9004, address, () => {
this.log("API | Connected to Airtouch");
this.GET_SYS_DETAILS(); // this should block the timeouts, want to get zone names before everything else happens

// request information from Airtouch after connection
setTimeout(this.GET_AC_STATUS.bind(this), 0);
setTimeout(this.GET_GROUP_STATUS.bind(this), 2000);
// schedule group status every 4.75 minutes to get updates for FakeGato history service
setInterval(this.GET_GROUP_STATUS.bind(this), 285000);

});
this.device.on("close", () => {
this.log("API | Disconnected from Airtouch");
Expand All @@ -293,7 +353,7 @@ AirtouchAPI.prototype.connect = function(address) {
let datalen = this.device.read(2);
let data = this.device.read(datalen.readUInt16BE());
let crc = this.device.read(2);
this.log("API | Received message with id " + msgid + " and data " + data.toString("hex"));
this.log("API | Received message with id " + msgid + " and type " + msgtype + " and data " + data.toString("hex"));
if (crc.readUInt16BE() != crc16([...header.slice(2), ...datalen, ...data])) {
this.log("API | ERROR: invalid crc");
return;
Expand All @@ -307,6 +367,9 @@ AirtouchAPI.prototype.connect = function(address) {
// decode ac status info
this.decode_ac_status(data);
break;
case MAGIC.MSGTYPE_SYS_DETAILS:
//decode system details
this.decode_sys_details(data);
}
});

Expand Down
6 changes: 5 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,11 @@ Airtouch.prototype.onACStatusNotification = function(ac_status) {
// callback for Group messages received from Airtouch Touchpad Controller
Airtouch.prototype.onGroupsStatusNotification = function(groups_status) {
groups_status.forEach(zone_status => {
zone_name = "Zone " + zone_status.group_number;
if (this.config.use_group_names) {
zone_name = "Zone " + this.api.zoneNames["Zone " + zone_status.group_number];
} else {
zone_name = "Zone " + zone_status.group_number;
}
this.log("Received status update for [" + zone_name + "]: " + JSON.stringify(zone_status));
// check if accessory exists
if (!(zone_name in this.zones)) {
Expand Down
3 changes: 3 additions & 0 deletions magic.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ module.exports = {

MSGTYPE_AC_STAT: 0x2d,

MSGTYPE_SYS_DETAILS: 0x2f,
MSGDATA_SYS_DETAILS: [0x55, 0x55, 0x80, 0xb0, 0x00, 0x2f, 0x00, 0x02, 0x03, 0xff, 0x16, 0xcd],

AC_POWER_STATES: {
KEEP: 0,
NEXT: 1,
Expand Down

0 comments on commit a47a0ab

Please sign in to comment.