softScheck / tplink-smartplug

TP-Link WiFi SmartPlug Client and Wireshark Dissector
Apache License 2.0
1.13k stars 296 forks source link

Simulation of an LB130 or sth. else #17

Open ovi1337 opened 7 years ago

ovi1337 commented 7 years ago

Hi, currently i'm trying to simulate a TP-Link smart lamp, because want to use own hardware which can talk with the tp-link protocol (hopefully including the cloud functionality)

I don't know what i'm doing wrong here, because i can see the try of the discovery in the commandline of the Kasa android app. The virtual Lamp won't be found in the app, but the search request is arrived in the simulation. Something seems to be missing. Can you please take a look?

const dgram = require('dgram');

const socket = dgram.createSocket({
  type: 'udp4',
  reuseAddr: true
});

function encrypt(input, firstKey) {
  if (typeof firstKey === 'undefined') firstKey = 0xAB;
  var buf = new Buffer(input.length); // node v6: Buffer.alloc(input.length)

  var key = firstKey;
  for (var i = 0; i < input.length; i++) {
    buf[i] = input.charCodeAt(i) ^ key;
    key = buf[i];
  }
  return buf;
};

function decrypt(input, firstKey) {
  if (typeof firstKey === 'undefined') firstKey = 0x2B;
  var buf = new Buffer(input); // node v6: Buffer.from(input)
  var key = firstKey;
  var nextKey;
  for (var i = 0; i < buf.length; i++) {
    nextKey = buf[i];
    buf[i] = buf[i] ^ key;
    key = nextKey;
  }
  return buf;
};

socket.on('error', function (err) {
  console.error('Client UDP error');
  console.trace(err);
  socket.close();
}.bind(this));

const systemData = {
  "system":{
  "get_sysinfo":{
  "sw_ver":"1.4.3 Build 170504 Rel.144921",
  "hw_ver":"1.0",
  "model":"LB130(EU)",
  "description":"Smart Wi-Fi LED Bulb with Color Changing",
  "alias":"TestLamp",
  "mic_type":"IOT.SMARTBULB",
  "dev_state":"normal",
  "mic_mac":"50C7xxxxxxxx",
  "deviceId":"8012459DB0CAAAB0FACF605DC492xxxxxxxxxxxx",
  "oemId":"D5C424D3C480911C980Exxxxxxxxxxxx",
  "hwId":"111E35908497A05512Exxxxxxxxxxxxxx",
  "is_factory":false,
  "disco_ver":"1.0",
  "ctrl_protocols":{
    "name":"Linkie",
    "version":"1.0"
  },
    "light_state":{
    "on_off":0,
    "dft_on_state":{
      "mode":"normal",
      "hue":120,
      "saturation":100,
      "color_temp":0,
      "brightness":10
    }
  },
  "is_dimmable":1,
  "is_color":1,
  "is_variable_color_temp":1,
  "preferred_state":[
    {
      "index":0,
      "hue":0,
      "saturation":0,
      "color_temp":2700,
      "brightness":50
    },
    {
      "index":1,
      "hue":0,
      "saturation":75,
      "color_temp":0,
      "brightness":100
    },
    {
      "index":2,
      "hue":120,
      "saturation":75,
      "color_temp":0,
      "brightness":100
    },
    {
      "index":3,
      "hue":240,
      "saturation":75,
      "color_temp":0,
      "brightness":100
    }
    ],
      "rssi":-21,
      "active_mode":"none",
      "heapsize":332364,
      "err_code":0
    }
  }
};

const lightDetailsData = {
  "on_off": 1,
  "mode": "normal",
  "hue": 120,
  "saturation": 100,
  "color_temp": 0,
  "brightness": 100,
  "err_code": 0
};

const lightStateData = {
  "on_off": 1,
  "mode": "normal",
  "hue": 120,
  "saturation": 100,
  "color_temp": 0,
  "brightness": 100,
  "err_code": 0
};

socket.on('message', function (msg, rinfo) {
  const decryptedMsg = decrypt(msg).toString('ascii');
  //const request = JSON.parse(decryptedMsg);

  var data = '{}';

  if(decryptedMsg.indexOf('"system":{"get_sysinfo":{') != -1) {
    data = JSON.stringify(systemData);
  }
  else
  if (decryptedMsg.indexOf('"smartlife.iot.smartbulb.lightingservice":{"get_light_details":{') != -1) {
    data = JSON.stringify(lightDetailsData);
  }
  else
  if (decryptedMsg.indexOf('"smartlife.iot.smartbulb.lightingservice":{"transition_light_state":{') != -1) {
    data = JSON.stringify(lightStateData);
  }

  console.log('REQUEST:\n' + decryptedMsg);
  console.log('FROM:\n' + rinfo.address + ':' + rinfo.port);
  console.log('ANSWER:\n' + data);

  var msgBuf = encrypt(data);

  socket.send(msgBuf, 0, msgBuf.length, rinfo.port, rinfo.address);

}.bind(this));

socket.bind(9999);

Thank you in advance for your help!

plasticrake commented 6 years ago

@ovi1337 I've written a simulator: https://github.com/plasticrake/tplink-smarthome-simulator I think the trick is you need to reply to the request for the cloud info in order for it to be added. It can also be slow to show up in the app.