Skip to content

Commit

Permalink
Merge pull request #132 from arteck/main
Browse files Browse the repository at this point in the history
  • Loading branch information
DutchmanNL authored Aug 15, 2024
2 parents de8c1ad + 375dc3d commit 7a05fa5
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 30 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ If you like my work, please feel free to provide a personal donation
(this is a personal Donate link for DutchmanNL, no relation to the ioBroker Project !)
[![Donate](https://raw.githubusercontent.com/DrozmotiX/ioBroker.switchbot-hub/main/admin/button.png)](http://paypal.me/DutchmanNL)


### coming soon
* (arteck) api V1.1

### 0.1.2 (2021-09-03)
* (Dutchman) Sentry error reporting implemented

Expand Down Expand Up @@ -134,4 +138,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.
8 changes: 8 additions & 0 deletions admin/jsonConfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@
"help": "Please use the Switchbot App to get your token, got to settings and tap 10 times on app version to generate it!",
"helpLink": "https://github.com/DrozmotiX/ioBroker.switchbot-hub/blob/main/README.md",
"sm": 9
},
"secretKey": {
"newLine": true,
"repeat": false,
"visible": false,
"type": "password",
"label": "Secret Key",
"sm": 9
},
"_intervallSettings": {
"newLine": true,
Expand Down
2 changes: 1 addition & 1 deletion lib/irRemoteDevices.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const irDeviceButtons = {
role: 'state',
states: {
on : 'On',
off : 'On',
off : 'Off',
},
def: 'off'
},
Expand Down
24 changes: 24 additions & 0 deletions lib/state_attr.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,30 @@ const state_attrb = {
def: false,
write: true,
},
'version': {
name: 'Version',
// type: 'number',
// role: 'value.temperature',
// unit: '',
// write: true,
// blacklist: true
},
'battery': {
name: 'Battery',
type: 'number',
role: 'value.battery',
unit: '%',
// write: true,
// blacklist: false
},
'deviceMode': {
name: 'deviceMode',
//type: 'number',
//role: 'value.battery',
//unit: '%',
// write: true,
// blacklist: false
},
};

module.exports = state_attrb;
105 changes: 77 additions & 28 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ const utils = require('@iobroker/adapter-core');
const stateAttr = require(`${__dirname}/lib/state_attr.js`); // Load attribute library
const irDeviceButtons = require(`${__dirname}/lib/irRemoteDevices.js`); // Load irRemote Button definitions
const {default: axios} = require('axios');
const crypto = require('crypto');
const https = require('https');
const { TextDecoder } = require('util');


const disableSentry = false; // Ensure to set to true during development !

Expand Down Expand Up @@ -172,38 +176,83 @@ class SwitchbotHub extends utils.Adapter {
* Make API call to SwitchBot API and return response.
* See documentation at https://github.com/OpenWonderLabs/SwitchBotAPI
*
* @param {string} [url] - Endpoint to handle API call, like `/v1.0/devices`
* @param {string} [url] - Endpoint to handle API call, like `/v1.1/devices`
* @param {object} [data] - Data for api post calls, if empty get will be executed
*/
apiCall(url, data) {
const ti = Date.now();
const dataIn = this.config.openToken + ti;
const signTerm = crypto.createHmac('sha256', this.config.secretKey)
.update(Buffer.from(dataIn, 'utf-8'))
.digest();
const sign = signTerm.toString("base64");
let methodSend = 'POST';
if (!data) {
methodSend = 'GET';
}

const options = {
hostname: 'api.switch-bot.com',
port: 443,
path: url,
method: methodSend,
headers: {
"Authorization": this.config.openToken,
"sign": sign,
"nonce": "",
"t": ti,
"Content-Type": "application/json; charset=utf8"
}
};
if (!url) throw new Error(`No URL provided, cannot make API call`);
if (!data) {
return axios(url, {
baseURL: 'https://api.switch-bot.com',
url: url,
timeout: 1000,
headers: {'Authorization': this.config.openToken}
})
.then(response => response.data)
.catch(error => {
throw new Error(`Cannot handle API call : ${error}`);
});
return new Promise((resolve, reject) => {
const req = https.request(options, res => {
let dataArray;

res.on('data', d => {
dataArray = d;
});

res.on('end', () => {
const out = new TextDecoder().decode(new Uint8Array(dataArray));
try {
resolve(JSON.parse(out));
} catch (err) {
reject(err);
}
});
});
req.on('error', error => {
reject(error);
});
req.end();
});
} else {
return axios.post(url, data, {
baseURL: 'https://api.switch-bot.com',
url: url,
timeout: 1000,
headers: {
'Content-Type': 'application/json;charset=UTF-8',
'Authorization': this.config.openToken,
}
})
.then(response => response.data)
.catch(error => {
throw new Error(`Cannot handle API call : ${error}`);
return new Promise((resolve, reject) => {
const req = https.request(options, res => {
let dataArray;

res.on('data', d => {
dataArray = d;
});

res.on('end', () => {
const out = new TextDecoder().decode(new Uint8Array(dataArray));
try {
resolve(JSON.parse(out));
} catch (err) {
reject(err);
}
});
});

req.on('error', error => {
reject(error);
});
req.write(data);
req.end();
});
}
}

Expand All @@ -212,7 +261,7 @@ class SwitchbotHub extends utils.Adapter {
try {

// Call API and get all devices
const apiResponse = await this.apiCall(`/v1.0/devices`);
const apiResponse = await this.apiCall(`/v1.1/devices`);
this.log.debug(`[getDevices API response]: ${JSON.stringify(apiResponse)}`);
if (!apiResponse) {
this.log.error(`Empty device list received, cannot process`);
Expand Down Expand Up @@ -303,7 +352,7 @@ class SwitchbotHub extends utils.Adapter {
this.log.debug(`All devices configuration data : ${JSON.stringify(this.devices)}`);

} catch (error) {
this.sendSentry(`[loadDevices]`, `${error}`);
// this.sendSentry(`[loadDevices]`, `${error}`);
this.setState('info.connection', false, true);
}
}
Expand All @@ -316,7 +365,7 @@ class SwitchbotHub extends utils.Adapter {
async deviceStatus(deviceId) {
try {

const apiResponse = await this.apiCall(`/v1.0/devices/${deviceId}/status`);
const apiResponse = await this.apiCall(`/v1.1/devices/${deviceId}/status`);
const devicesValues = apiResponse.body;
this.log.debug(`[deviceStatus apiResponse ]: ${JSON.stringify(apiResponse)}`);
if (!devicesValues || Object.keys(devicesValues).length === 0) {
Expand Down Expand Up @@ -514,7 +563,7 @@ class SwitchbotHub extends utils.Adapter {
const deviceType = this.devices[deviceArray[2]].deviceType;

// Default configuration for SmartBot POST api
const apiURL = `/v1.0/devices/${deviceId}/commands`;
const apiURL = `/v1.1/devices/${deviceId}/commands`;
const apiData = {
'command': 'setAll',
'parameter': state.val,
Expand Down Expand Up @@ -652,4 +701,4 @@ if (require.main !== module) {
} else {
// otherwise start the instance directly
new SwitchbotHub();
}
}

0 comments on commit 7a05fa5

Please sign in to comment.