MEL - Local Control
sburke781 opened this issue · comments
Expand the Unified Thermostat Drivers to include local control of air conditioning units, removing the reliance on the cloud services.
- Store Password as State Variable
- Store Crypto Serial as State Variable
- Store Device IP Address as State Variable
- Add Local Control Preference Setting to unit child driver
- Develop Encode Command method for Kumo platform
- Develop unitCommand_KumoCloud_Local method to issue local commands
- Update heat_KumoCloud and cool_KumoCloud methods to call local unit command method above
- Update setTemperature_KumoCloud and setThermostatFanMode_KumoCloud methods
- Update on_KumoCloud and off_KumoCloud methods
- Update retrieveSettings_KumoCloud method
- Update retrieveStatusInfo_KumoCloud method
- Include Device IP Override command
Following communications issues for @bikesquid in recent days, I have taken another look at Fraser Sim's Typescript example for Homebridge and have made some note's on the encode token method:
// calcuate a token - based on pykumo and homebridge-kumo-local
const W = this.h2l(KUMO_KEY);
const p = base64.decode(password);
const data_hash = sjcl.codec.hex.fromBits(
sjcl.hash.sha256.hash(
sjcl.codec.hex.toBits(
this.l2h(
Array.prototype.map.call(p + post_data, (m2) => {
return m2.charCodeAt(0);
}),
),
),
),
);
// convert data_hash to byteArray
const data_hash_byteArray = this.h2l(data_hash);
// Part # 1 - Decode the password
const p = base64.decode(password);
Returns a byte[] or string(?) of decoded password string from Kumo
// Encode
def encoded = text.bytes.encodeBase64().toString()
println encoded
// Decode
byte[] decoded = encoded.decodeBase64()
println new String(decoded)
// Part # 2
SHA256 Hash
Could originalString below just be = password.decodeBase64() + post_data
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] encodedhash = digest.digest(
originalString.getBytes(StandardCharsets.UTF_8));
producing data_hash_byteArray from Typescript example
// Part # 3
Mashing together data_hash_byteArray, Kumo Key and CryptoSerial
const intermediate = new Uint8Array(88);
for (let i = 0; i < 32; i++) {
intermediate[i] = W[i];
intermediate[i + 32] = data_hash_byteArray[i];
}
intermediate[64] = 8;
intermediate[65] = 64;
intermediate[66] = 0; //S_PARAM
// convert cryptoSerial to byte array
const cryptoserial = this.h2l(cryptoSerial);
intermediate[79] = cryptoserial[8];
for (let i = 0; i < 4; i++) {
intermediate[i + 80] = cryptoserial[i + 4];
intermediate[i + 84] = cryptoserial[i];
}
This should all translate easily as quivalent array manipulation in Groovy
// Part # 4
Do SHA-256 hash of intermediate Byte array
const hash = sjcl.codec.hex.fromBits(
sjcl.hash.sha256.hash(sjcl.codec.hex.toBits(this.l2h(intermediate))),
);
return hash;
Use Message Digest again.... Without needing to convert a string to a byte array
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] encodedhash = digest.digest(
originalString.getBytes(StandardCharsets.UTF_8));
Convert encodedHash[] to Hex String
private static String bytesToHex(byte[] hash) {
StringBuilder hexString = new StringBuilder(2 * hash.length);
for (int i = 0; i < hash.length; i++) {
String hex = Integer.toHexString(0xff & hash[i]);
if(hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}