YoLink integration

In the last 30 days I have purchased 15 door sensors, 5 water sensors, 2 motion sensors, 2 outdoor sensors, a water valve, 4 outdoor contact sensors, 2 garage door kits, and several temp sensors.

All going back. I have some others but they are beyond the return period so Im stuck with them. Love the system but ill go with some other stuff that I know works with Home Assistant.

I can buy some of those sensors from you
 Please send me a dm with details?

They are going back to amazon. All new in the box. It is much easier for me plus I get all my money back.

Forgive my naivetĂ© since I’m not a frequent GitHub user, but isn’t this an open PR? Add YoLink product integration by matrixd2 · Pull Request #69167 · home-assistant/core · GitHub

Just wondering if I’m reading things wrong


2 Likes

Good find! There are at least 2 others Closed. I didn’t find this earlier, so looks like there may be something still in motion.

1 Like

I was looking through the thread
 someone already posted how to get the API creds from the app but no one has really posted how to use them in a meaningful way within HA. Since I’ve had MQTT running successfully via Node Red, I’m going to put together a quick little tutorial tonight and post it. This isn’t for the faint of heart and it took quite a bit of Googling but hopefully it’ll give some the help they are looking for to at least make use of their sensors. I will say that their MQTT server appears to be solid and I haven’t had any major issues with it, so that’s a plus.

Edit: I ran into a VPN issue tonight and didn’t have a chance to get around to this. I’ll work on it tomorrow (4/6) – sorry for the delay!

6 Likes

@xcesmess that would be awesome. I would love to see what you share!

Checking back in on this thread to see the PR still hasn’t gotten anywhere :disappointed:

I was able to get their integration running as a custom component, after reading more on their oauth API and smacking python with a wrench to fix some imports.
The oauth endpoint they’ve coded the integration for (v1 of the open API from their docs) requires what they call a CSID as the client id in HA, and doesn’t work with the user access credentials they give you in the app. Their CSID oauth doesn’t appear to actually use the CSSecKey to generate the token, so I just borrowed the CSID they’re using to connect Alexa. Probably goes against ToS somewhere, but it’s been working for a few days now with no problems :man_shrugging:

Oh no, someone commented on the PR. Time to close it and open a new one.

Yeah bummer it didn’t make it into todays release

I have given up on waiting for the integration from HA from them and as a temporary stopgap I am using IFTTT webhooks in HA which they support. It’s easier than dealing with the API - you can get API keys from within the mobile APP (don’t have to email to ask for them anymore) - but even that is not needed for IFTTT

Can you check and give us an update on the ETA with all the back and forth between your dev’s and HA QA/UAT for the integration to be released?

Just for reference you can see all their yolink tagged PR here.

1 Like

Okay as promised
 this is how you get MQTT working within Home Assistant by way of Node Red. Yes, this does use the cloud and I understand the risks, blah blah blah
 this is just to help those that want to make use of their sensors and not cobble something together or rely on IFTTT.

This first documentation will cover the initial (legacy?) API access. I’ll write up on a follow-up post on how to use the app-based API.

Be sure you have Node Red installed – you can do this in Home Assistant by going to Configuration → Add-ons, Backups & Supervisor → Add-ons tab → Add-on Store. You’ll find Node-Red under the Home Assistant Community Add-ons.

To make this easier, I’ve created a sample flow that you can import into Node-Red. To import this, open up Node-Red on the left. If this is your first time opening Node-Red, it will create a blank tab that you can work on. Click on the three dots in the upper right and select Import. Copy the text below and paste it into this window and click Import. A new tab will be added called Flow 1 with the nodes.

[{"id":"c731b68e7e93d637","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"cf49b4468439e5aa","type":"mqtt in","z":"c731b68e7e93d637","name":"YoLink MQTT","topic":"{CSName}/#","qos":"2","datatype":"auto","broker":"dcbbcf25a3deef7b","nl":false,"rap":true,"rh":0,"inputs":0,"x":170,"y":140,"wires":[["5a4bf1f398aa126f"]]},{"id":"ba3da4f3e73c8fa3","type":"comment","z":"c731b68e7e93d637","name":"Enabling API access for YoLink Device","info":"1. Open the App on your phone and go to the device you want to enable API access for. \n2. Click on the three dots in the upper right.\n3. Scroll down to SN and click on the QR code.\n4. Screenshot this and print it out.\n5. Go to https://www.the-qrcode-generator.com/scan and scan the QR code you printed. You will be presented with a number, save that serial number down.\n6. Next, open MQTT Explorer and create a new MQTT connection. Use the following connection parameters:\n\n Host: api.yosmart.com Port: 8003\n User: <Your CSID>\n Pass: <MD5 hash of your CSSecKey>\n \n Save and Connect.\n7. In the MQTT explorer window, locate the publish section on the right side. Expand it if necessary.\n8. In the Topic line, enter the following topic for the first device you'd like to add:\n <CSID>/<DEVICE_SN>/request\n9. Set the type to 'json'.\n10. In the text box, enter the following:\n\n { \"method\": \"Manage.addYoLinkDevice\",\n \"time\": <EPOCH_TIME>,\n \"params\": { \"sn\": \"<DEVICE_SN>\" }}\n \n Replace <DEVICE_SN> with the device serial number you're adding.\n \n Replace <EPOCH_TIME> with the time value from https://www.epochconverter.com/\n\n11. Click the Publish button.\n12. If all goes well, you should see a response in the topic <CSID>/<DEVICE_SN>/response that matches the serial number. It should explain the type of device and have a code of \"000000\".\n13. Grab the 'token' that is listed, you will need that for all future requests. You will continue to get information in <CSID>/<DEVICE_SN>/report for each sensor added.\n \n\n\n\n\n\n\n\n\nRequest: {username}/<DEVICE_SN>/request\nResponse: {username}/<DEVICE_SN>/response\n\nTemp Sensor Method: THSensor.getState\n\n\n","x":450,"y":60,"wires":[]},{"id":"5a4bf1f398aa126f","type":"json","z":"c731b68e7e93d637","name":"Parse JSON","property":"payload","action":"","pretty":false,"x":310,"y":240,"wires":[["734eec60711d5905","1abd5af51bdbba4b"]]},{"id":"734eec60711d5905","type":"switch","z":"c731b68e7e93d637","name":"Device Selector","property":"payload.deviceId","propertyType":"msg","rules":[{"t":"eq","v":"{device1}","vt":"str"},{"t":"eq","v":"{device2}","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":440,"y":360,"wires":[["bf54159158f2f41b","cebe5e6e6461c9c0","47990cde1f470a4f"],["66bd633936ed1ddb","ef09aeda9d7e752f","c787b835989fc2da","8aacaf2332bc5c11"]]},{"id":"bf54159158f2f41b","type":"ha-entity","z":"c731b68e7e93d637","name":"Garage Freezer Temp Sensor Status","server":"1a70fbd4.64fc74","version":2,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Garage Freezer Temp Sensor Status"},{"property":"device_class","value":""},{"property":"icon","value":""},{"property":"unit_of_measurement","value":""},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"state":"payload.data.state","stateType":"msg","attributes":[{"property":"version","value":"payload.data.version","valueType":"msg"},{"property":"tempCorrection","value":"payload.data.tempCorrection","valueType":"msg"},{"property":"loraSignal","value":"payload.data.loraInfo.signal","valueType":"msg"},{"property":"gatewayId","value":"payload.data.loraInfo.gatewayId","valueType":"msg"},{"property":"gateways","value":"payload.data.loraInfo.gateways","valueType":"msg"},{"property":"humidityCorrection","value":"payload.data.humidityCorrection","valueType":"msg"},{"property":"mode","value":"payload.data.mode","valueType":"msg"},{"property":"interval","value":"payload.data.interval","valueType":"msg"},{"property":"msgid","value":"payload.msgid","valueType":"msg"}],"resend":true,"outputLocation":"payload","outputLocationType":"none","inputOverride":"allow","outputOnStateChange":false,"outputPayload":"$entity().state ? \"on\": \"off\"","outputPayloadType":"jsonata","x":830,"y":100,"wires":[[]]},{"id":"1abd5af51bdbba4b","type":"debug","z":"c731b68e7e93d637","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":490,"y":140,"wires":[]},{"id":"38d5dbe64d88bb1b","type":"ha-entity","z":"c731b68e7e93d637","name":"Garage Freezer Temperature","server":"1a70fbd4.64fc74","version":2,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Garage Freezer Temperature"},{"property":"device_class","value":""},{"property":"icon","value":""},{"property":"unit_of_measurement","value":"°F"},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"state":"payload.data.temperature","stateType":"msg","attributes":[],"resend":true,"outputLocation":"payload","outputLocationType":"none","inputOverride":"allow","outputOnStateChange":false,"outputPayload":"$entity().state ? \"on\": \"off\"","outputPayloadType":"jsonata","x":940,"y":160,"wires":[[]]},{"id":"cebe5e6e6461c9c0","type":"change","z":"c731b68e7e93d637","name":"C to F","rules":[{"t":"set","p":"payload.data.temperature","pt":"msg","to":"payload.data.temperature * 1.8 + 32","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":730,"y":160,"wires":[["38d5dbe64d88bb1b"]]},{"id":"47990cde1f470a4f","type":"ha-entity","z":"c731b68e7e93d637","name":"Garage Freezer Temp Sensor Battery Alarm","server":"1a70fbd4.64fc74","version":2,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Garage Freezer Temp Sensor Battery Alarm"},{"property":"device_class","value":""},{"property":"icon","value":""},{"property":"unit_of_measurement","value":""},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"state":"payload.data.alarm.lowBattery","stateType":"msg","attributes":[{"property":"battery","value":"payload.data.battery","valueType":"msg"}],"resend":true,"outputLocation":"payload","outputLocationType":"none","inputOverride":"allow","outputOnStateChange":false,"outputPayload":"$entity().state ? \"on\": \"off\"","outputPayloadType":"jsonata","x":850,"y":40,"wires":[[]]},{"id":"66bd633936ed1ddb","type":"ha-entity","z":"c731b68e7e93d637","name":"Master Bathroom TH Sensor Battery Alarm","server":"1a70fbd4.64fc74","version":2,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Master Bathroom TH Sensor Battery Alarm"},{"property":"device_class","value":""},{"property":"icon","value":""},{"property":"unit_of_measurement","value":""},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"state":"payload.data.alarm.lowBattery","stateType":"msg","attributes":[{"property":"battery","value":"payload.data.battery","valueType":"msg"}],"resend":true,"outputLocation":"payload","outputLocationType":"none","inputOverride":"allow","outputOnStateChange":false,"outputPayload":"$entity().state ? \"on\": \"off\"","outputPayloadType":"jsonata","x":850,"y":380,"wires":[[]]},{"id":"ef09aeda9d7e752f","type":"ha-entity","z":"c731b68e7e93d637","name":"Master Bathroom TH Sensor Status","server":"1a70fbd4.64fc74","version":2,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Master Bathroom TH Sensor Status"},{"property":"device_class","value":""},{"property":"icon","value":""},{"property":"unit_of_measurement","value":""},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"state":"payload.data.state","stateType":"msg","attributes":[{"property":"version","value":"payload.data.version","valueType":"msg"},{"property":"tempCorrection","value":"payload.data.tempCorrection","valueType":"msg"},{"property":"loraSignal","value":"payload.data.loraInfo.signal","valueType":"msg"},{"property":"gatewayId","value":"payload.data.loraInfo.gatewayId","valueType":"msg"},{"property":"gateways","value":"payload.data.loraInfo.gateways","valueType":"msg"},{"property":"humidityCorrection","value":"payload.data.humidityCorrection","valueType":"msg"},{"property":"mode","value":"payload.data.mode","valueType":"msg"},{"property":"interval","value":"payload.data.interval","valueType":"msg"},{"property":"msgid","value":"payload.msgid","valueType":"msg"}],"resend":true,"outputLocation":"payload","outputLocationType":"none","inputOverride":"allow","outputOnStateChange":false,"outputPayload":"$entity().state ? \"on\": \"off\"","outputPayloadType":"jsonata","x":820,"y":440,"wires":[[]]},{"id":"c787b835989fc2da","type":"change","z":"c731b68e7e93d637","name":"C to F","rules":[{"t":"set","p":"payload.data.temperature","pt":"msg","to":"payload.data.temperature * 1.8 + 32","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":730,"y":500,"wires":[["3acb1d99cdd29169"]]},{"id":"3acb1d99cdd29169","type":"ha-entity","z":"c731b68e7e93d637","name":"Master Bathroom Temperature","server":"1a70fbd4.64fc74","version":2,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Master Bathroom Temperature"},{"property":"device_class","value":""},{"property":"icon","value":""},{"property":"unit_of_measurement","value":"°F"},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"state":"payload.data.temperature","stateType":"msg","attributes":[],"resend":true,"outputLocation":"payload","outputLocationType":"none","inputOverride":"allow","outputOnStateChange":false,"outputPayload":"$entity().state ? \"on\": \"off\"","outputPayloadType":"jsonata","x":950,"y":500,"wires":[[]]},{"id":"8aacaf2332bc5c11","type":"ha-entity","z":"c731b68e7e93d637","name":"Master Bathroom Humidity","server":"1a70fbd4.64fc74","version":2,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Master Bathroom Humidity"},{"property":"device_class","value":""},{"property":"icon","value":""},{"property":"unit_of_measurement","value":"%"},{"property":"state_class","value":""},{"property":"last_reset","value":""}],"state":"payload.data.humidity","stateType":"msg","attributes":[],"resend":true,"outputLocation":"payload","outputLocationType":"none","inputOverride":"allow","outputOnStateChange":false,"outputPayload":"$entity().state ? \"on\": \"off\"","outputPayloadType":"jsonata","x":800,"y":560,"wires":[[]]},{"id":"dcbbcf25a3deef7b","type":"mqtt-broker","name":"yolink","broker":"api.yosmart.com","port":"8003","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"sessionExpiry":"","credentials":{"user":"{CSID}","password":"password"}},{"id":"1a70fbd4.64fc74","type":"server","name":"Home Assistant","version":2,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":30}]

Finishing the MQTT setup:

  1. Open the Yolink MQTT object by double-clicking on it. Click on the pencil icon next to the yolink server.
  2. In this window, click on the Security tab. On this tab, enter your CSID for the Username and then enter an MD5 hash of your CSSecKey for the password. For MD5 hashing, you can use https://www.md5hashgenerator.com/. Click Update on the upper right to close the server screen.
  3. Back on the MQTT page, change the Topic box to your CSName/# (for instance, johnnyqman/#). Click Update in the upper right.

When you deploy this, it will connect to MQTT and start listening to device statuses from your hub. I have two devices shown as examples there to help you configure your devices
 a YS8003 and outdoor temp sensor with probe (I couldn’t find the model number). I do have outdoor gate sensors but I don’t have them added in here at the moment. Unfortunately none of your sensors have been configured to send data across the API. To do this, we will need to make some MQTT requests to the API for this to happen.

To enable API access, you can use MQTT Explorer (http://mqtt-explorer.com/) to send your MQTT commands.

  1. Open the App on your phone and go to the device you want to enable API access for.

  2. Click on the three dots in the upper right.

  3. Scroll down to SN and click on the QR code.

  4. Screenshot this and print it out.

  5. Go to Scan QR Codes with your WebCam and use your webcam to scan the QR code you printed. You will be presented with a number, save that serial number down.

  6. Next, open MQTT Explorer and create a new MQTT connection using the information below. Use the following connection parameters:

    Host: api.yosmart.com Port: 8003
    User: Your CSID
    Pass: MD5 hash of your CSSecKey

    Save and Connect.

  7. In the MQTT explorer window, locate the publish section on the right side. Expand it if necessary.

  8. In the Topic line, enter the following topic for the first device you’d like to add:
    CSID/DEVICE_SN/request

  9. Set the type to ‘json’.

  10. In the text box, enter the following:

    { “method”: “Manage.addYoLinkDevice”,
    “time”: EPOCH_TIME,
    “params”: { “sn”: “DEVICE_SN” }}

    Replace DEVICE_SN with the device serial number you’re adding.

    Replace EPOCH_TIME with the time value from https://www.epochconverter.com/

  11. Click the Publish button.

  12. If all goes well, you should see a response in the topic CSID/DEVICE_SN/response that matches the serial number. It should explain the type of device and have a code of “000000”.

  13. Grab the ‘token’ that is listed, you will need that for all future requests. You will continue to get information in CSID/DEVICE_SN/report for each sensor added.

  14. Create an MQTT request for every device that you need to enable API access for.

Now that we’ve enabled API access for our sensors, we need to add them to Node-Red so it. can start sending data to HA. Go back to Node-Red and continue below.

  1. Double click on the Device Selector node.
  2. Change the {device1} and {device2} entries to match the tokens that you received from enabling the API access in MQTT Explorer. It should be a string of about 15-20 alphanumeric characters. There will be one for each device. If you have more than two, click the +add button at the bottom to add another item.
  3. Click Update when you’re done.
  4. When a message comes in with the specific token, it will be directed to the respective point on the switch node. From there you can tell HA what to do.

Hopefully this should give some a starting point. I wrote this in bit of a rush so it may be a little jumbled. I don’t have any extra sensors that I can go through the actual process with. Once I figure out how to get my auth token from the app API access I’ll update.

6 Likes

I have found the IFTTT webhooks very unreliable and misses events from my door sensors fairly often.
Alexa routines have been more reliable and faster for me anyway.
The API is a bit of work, but find it very stable and faster.
The YoLink discord community has great support and example code.
Also waiting for the official integration to reduce the complexity of the expiring tokens.

@xcesmess hey man I tried for a while and I could not import the flow you shared. all I got was SyntaxErrors from the import tool in node-red. Are there any dependencies I need to have in my Node-Red ?

I’ve got 9 YoLink devices and am holding off on buying any more until there is HA integration, or at least a solid workaround that doesn’t require the above :slight_smile:

1 Like

@xcesmess I also can confirn that the nodered flow provided has errors in it. This happens a lot with copy and paste. Could you please export your flow as a file and upload it for us. Thanks.

Well shoot
 let me take a look and see what happened.

Give that a shot now
 I tried to upload as a TXT file but it only allows me to upload gif, jpg, png, etc. The problem was the double quotes were converted to the fancy type
 I didn’t have it set as preformatted text initially.

I haven’t had an opportunity to work on the new API model yet. I ran into difficulties getting my API key to authenticate with a Postman making the POST request. It would always come back with auth failed when trying to get the token. From other posts, it looks like that token may not be permanent so it may not be worth messing with.