TheAgentK / tuya-mqtt

Nodejs-Script to combine tuyaapi and openhab via mqtt
MIT License
173 stars 81 forks source link

Can't get version 3 to work #43

Closed Trauma closed 3 years ago

Trauma commented 3 years ago

I'm certainly missing somthing dumb, version 2 was working fine with somewhat the same setup.

Here is my config :

Dockerfile

FROM node

RUN git clone --single-branch --branch dev https://github.com/TheAgentK/tuya-mqtt.git && \
    cd tuya-mqtt && \
    npm install

WORKDIR /tuya-mqtt

COPY config.json .

ENV DEBUG=*

ENTRYPOINT ["node", "tuya-mqtt.js"]

relevant docker-compose conf:

  tuya-mqtt:
    container_name: tuya-mqtt
    image: tromatik/tuya-mqtt
    depends_on:
      - mqtt-broker
    volumes:
      - ./tuya-mqtt/config.json:/tuya-mqtt/config.json
      - ./tuya-mqtt/devices.conf:/tuya-mqtt/devices.conf
    restart: always
    environment:
      - TZ=Europe/Paris
      - DEBUG=-*
    networks:
      backend:
      physical:
        ipv4_address: 192.168.0.4

config.json

{
    "host": "192.168.0.10",
    "port": 1883,
    "topic": "tuya/",
    "mqtt_user": "",
    "mqtt_pass": "",
    "qos": 2
}

device.conf

[
  {
    name: 'LED SMART 2',
    id: 'bff590a2c25cf0a2bazufd',
    key: '607663889df63108',
    version: '3.3'
  },
  {
    name: 'Smart Switch 1',
    id: 'bf84deb2a2b0c4496bsrsf',
    key: '9f95ebd825dbac96',
    version: '3.3'
  },
  {
    name: 'Smart Plug',
    id: 'bf22ba559b69252a12fldr',
    key: '473fac1b23a77103',
    version: '3.3'
  }
]

Test OK with tuya-cli : tuya-cli set --id bff590a2c25cf0a2bazufd --key 607663889df63108 --dps 1 --set true/false

Test KO when publishing tuya/bff590a2c25cf0a2bazufd/dps/1/command true

Logs when publishing to mqtt :

2020-10-09T22:06:43.696Z mqttjs:client writable stream :: parsing buffer
2020-10-09T22:06:43.696Z mqtt-packet:parser parse: current state: _parseHeader
2020-10-09T22:06:43.697Z mqtt-packet:parser _parseHeader: packet: Packet { cmd: 'publish', retain: false, qos: 0, dup: false, length: -1, topic: null, payload: null }
2020-10-09T22:06:43.697Z mqtt-packet:parser parse: state complete. _stateCounter is now: 1
2020-10-09T22:06:43.697Z mqtt-packet:parser parse: packet.length: -1, buffer list length: 49
2020-10-09T22:06:43.697Z mqtt-packet:parser _parseVarByteNum
2020-10-09T22:06:43.697Z mqtt-packet:parser parse: packet.length: 48, buffer list length: 48
2020-10-09T22:06:43.699Z mqtt-packet:parser _parsePayload: payload BufferListStream {
  _bufs: [
  _writableState: WritableState {
    objectMode: false,
    highWaterMark: 16384,
    finalCalled: false,
2020-10-09T22:06:56.041Z mqttjs:client _checkPing :: checking ping...
2020-10-09T22:06:56.046Z mqttjs:client _checkPing :: ping response received. Clearing flag and sending `pingreq`
2020-10-09T22:06:56.048Z mqttjs:client _sendPacket :: (mqttjs_57bc5e7b) ::  start
2020-10-09T22:06:56.050Z mqttjs:client sendPacket :: packet: { cmd: 'pingreq' }
2020-10-09T22:06:56.051Z mqttjs:client sendPacket :: emitting `packetsend`
2020-10-09T22:06:56.052Z mqttjs:client sendPacket :: writing to stream
2020-10-09T22:06:56.052Z mqtt-packet:writeToStream generate called
2020-10-09T22:06:56.053Z mqtt-packet:writeToStream generate: packet.cmd: pingreq
2020-10-09T22:06:56.054Z mqttjs:client sendPacket :: writeToStream result true
2020-10-09T22:06:56.055Z mqttjs:client writable stream :: parsing buffer
2020-10-09T22:06:56.055Z mqtt-packet:parser parse: current state: _parseHeader
2020-10-09T22:06:56.056Z mqtt-packet:parser _parseHeader: packet: Packet { cmd: 'pingresp', retain: false, qos: 0, dup: false, length: -1, topic: null, payload: null }
2020-10-09T22:06:56.057Z mqtt-packet:parser parse: state complete. _stateCounter is now: 1
2020-10-09T22:06:56.058Z mqtt-packet:parser parse: packet.length: -1, buffer list length: 1
2020-10-09T22:06:56.058Z mqtt-packet:parser _parseVarByteNum
2020-10-09T22:06:56.059Z mqtt-packet:parser _parseVarByteNum: result: { bytes: 1, value: 0 }
2020-10-09T22:06:56.060Z mqtt-packet:parser _parseLength 0
2020-10-09T22:06:56.060Z mqtt-packet:parser parse: state complete. _stateCounter is now: 2
2020-10-09T22:06:56.061Z mqtt-packet:parser parse: packet.length: 0, buffer list length: 0
2020-10-09T22:06:56.062Z mqtt-packet:parser _parsePayload: payload BufferListStream {
  _bufs: [],
    needDrain: false,
    ending: false,
    ended: false,
2020-10-09T22:06:56.067Z mqtt-packet:parser _parsePayload complete result: true
2020-10-09T22:06:56.068Z mqtt-packet:parser parse: state complete. _stateCounter is now: 3
2020-10-09T22:06:56.069Z mqtt-packet:parser parse: packet.length: 0, buffer list length: 0
2020-10-09T22:06:56.069Z mqtt-packet:parser _newPacket
2020-10-09T22:06:56.070Z mqtt-packet:parser _newPacket: parser emit packet: packet.cmd: pingresp, packet.payload: null, packet.length: 0
2020-10-09T22:06:56.070Z mqttjs:client parser :: on packet push to packets array.
2020-10-09T22:06:56.071Z mqtt-packet:parser _newPacket: new packet
2020-10-09T22:06:56.071Z mqtt-packet:parser parse: state complete. _stateCounter is now: 4
2020-10-09T22:06:56.072Z mqtt-packet:parser parse: packet.length: -1, buffer list length: 0
2020-10-09T22:06:56.072Z mqtt-packet:parser parse: exited while loop. packet: -1, buffer list length: 0
2020-10-09T22:06:56.073Z mqttjs:client work :: getting next packet in queue
2020-10-09T22:06:56.073Z mqttjs:client work :: packet pulled from queue
2020-10-09T22:06:56.074Z mqttjs:client _handlePacket :: emitting packetreceive
tsightler commented 3 years ago

Most likely it's just a lack of documentation since that's a task that's still outstanding before I can publish 3.0.

Since you have device names in you devices config the code will use it for the topic instead of the device id so, for example, your device named LED SMART 2 would be as follows:

tuya/led_smart_2/dps/1/command

You may also need to add type: GenericDevice, to each device in devices.conf although it should default to that but I can't remember if I've implemented fall through if no device type is defined you. I think I did, but I'll have to check it when I get back to a computer.

tsightler commented 3 years ago

Also, please use DEBUG=tuya-mqtt:* to get useful debug data. I'm not sure what the data you posted is.

Trauma commented 3 years ago

Adding the type: GenericDevice to the config was the key. So I would say it's not defaulting to this value, look at the logs:

2020-10-10T07:44:28.997Z tuya-mqtt:mqtt Device type not specified, skipping creation of this device
2020-10-10T07:44:28.997Z tuya-mqtt:mqtt Device type not specified, skipping creation of this device
2020-10-10T07:44:28.997Z tuya-mqtt:mqtt Device type not specified, skipping creation of this device

BTW thanks for the logging configuration tip ;)

Trauma commented 3 years ago

So I've configured my device according what I could find in the code. So far SimpleSwitch and GenericDevice HA discovery works fine. For RGBTWLight while on the tuya api side it seems fine, I'm wondering if the brightness and color_temp state topics aren't swapped.. not sure. Is there a way to configure the tuya to mqtt mapping/templating for testing ?

Thanks

tsightler commented 3 years ago

I have quite a large number of pending updates for RGBTWLight in my local branch that I'll hopefully push sometime this weekend. The code that's currently pished there doesn't support color temp, only white level (brightness in white mode). It's pretty much impossible for brightness and whitelevel to be swapped because of how Tuya bulbs store these values.

Basically, there are 5 DPS values that control tuya bulbs (more for built in scenes like "rainbow", etc. if your device supports those but I'm not focused on those right now since it seems not possible to predict them):

dpsPower = ON/OFF dpsMode = While/Color (also scenes if your bulb supports custom scene modes in the Tuya app, unless you use the DPS values directly) dpsWhiteLevel = White mode brightness (I'm using the Home Assistant term white level), this only controls brightness when the bulb is in white mode and is in either 0-255 or 0-1000 scale dpsColorTemp = White mode color temperature in either 0-255 or 0-1000 scale. There is no direct map to mireds so conversion is just an estimate (can be overridden if you know your bulbs exact color range) dpsColor = the HSB value for color mode in a Tuya custom format, HSB or HSBHEX. Both are hex interestingly, but HSB, is a simple, zero padded hex where H = 0-360, S = 0-1000 and B i= 0-1000, converted to their hex value and padded with zeros to make a 12 character HEX string. HSBHEX is still HSB, with H = 0-360, S= 0-255, B=0-255, but then encoded into a weird, 14 character hex string that requires some weird math to get there.

In general, bulbs use either DPS 1-5 or DPS 20-24. The former so far seem to usually be HSBHEX style and use 0-255 scale for brightness/saturation/white level/colortemp, while the latter seem to usually be HSB style with 0-1000 scale, at least so far this pattern has held for the devices I have or have seen customers use the code with. However, the code doesn't currently assume this is completely true, it tries to detect HSB/HSBHEX mode regardless of what DPS range the bulb uses and uses this as the likely indicator of scale for other values.

Pretty much all values can be overridden by the config file, If you look at the top sections of code you'll see a section where, for example, this.config.dpsColor is set, that means that you can manually override this option by setting dpsColor in the devices.conf.

However, if the device is changing color, you probably don't need to do this, as that pretty much means it's using the proper DPS key for color since HSB values are all stored in a single DPS key. What behavior are you seeing that makes you think they might be switched? I've put a lot of work into the code in my local branch to try to improve the white/color switch behavior, so perhaps once I push that it will help. It's really that code, and the documentation, which is the last piece I need to finish before pushing 3.0.

Trauma commented 3 years ago

Ok thanks for all these explanations, it make sense.

It's a misunderstanding on my side, I thought brightness_state and it's command counterpart was the actual brightness command... well the name is confusing isn't it :). It's indeed for brightness but only in color mode... The whitevalue* are the brightness i was looking for, the one for white mode.

On my setup brightness_state topic always sticks to 100, whatever the mode or the settings of the bulb. I think the swap filling i had came from this.

I'll wait your next push to perform further testing.

BR.

tsightler commented 3 years ago

It's pretty standard for bulbs that have separate brightness levels for white/color mode to use the brightness/white_level construct, which is why projects like Home Assistant implement this in their light integrations. It mirrors the same behavior of the Tuya/SmartLife app, which has separate brightness on the white vs color page.

I've considered adding logic in the code to try to flip the function of brightness based on the mode of the light, but that leaves one less way to know whether the light needs to flip between modes, especially for lights that don't support color temperature in white mode. That being said, I'm interested in feedback on this or any other ideas.