sidoh / esp8266_milight_hub

Replacement for a Milight/LimitlessLED hub hosted on an ESP8266
MIT License
937 stars 220 forks source link

Version with original LT8900(LT8910-8920) module #18

Closed itProfi closed 7 years ago

itProfi commented 7 years ago

Chris! Is it possible make version of library with support original LT8910 module support? It's fully describe in https://bitbucket.org/robvanderveer/lt8900lib 21-03-2017 085506 IMHO is easer and simple, that use VIRTUAL NRF24... I use it to decode all packets. It's cost in Cina on Taobao - ¥ 3.35 ( 约USD 0.49) This guys also use this module https://authometion.com/shop/it/ Their forum -http://www.authometion.com/forum/viewforum.php?f=2 Their repo - https://github.com/pmoscetta/authometion-milight

sidoh commented 7 years ago

Nice, I like this! :)

itProfi commented 7 years ago

Nice, I like this! :)

But i am beginner in С++ and I not able to write this LT8910 version, but i ready to help you :)

itProfi commented 7 years ago

Chris, it's possible, that you can make in foreseeable future library with support LT8910 or no? :)

sidoh commented 7 years ago

I like the idea from a cleanliness perspective, but given that Henryk's PL1167 emulator code works pretty well, and NRF24L01s seem to be more available, I'm not sure there's much practical value.

What are the biggest advantages that you see?

itProfi commented 7 years ago

Probably you are right. Simply at the first stage, it was much easier for me, as a beginner, to work and explore data packets, using literally small sketches .. And in practical application, it is possible that it is not needed.

itProfi commented 7 years ago

include

include "LT8900.h"

include

include

const char ssid = ".."; // cannot be longer than 32 characters! const char pass = "..."; // WiFi password

const uint8_t PIN_NRF_RST = 4; const uint8_t PIN_NRF_CS = 5; const uint8_t PIN_NRF_PKT = 10; uint8_t bufer;

LT8900 lt(PIN_NRF_CS, PIN_NRF_PKT, PIN_NRF_RST);

//Thanks to Henryk and Erantimus for providing details and checksum code. //Calculate Checksum - Returns 2 bytes.

uint8_t recieve_code() { uint8_t bbuf[20]; int packetSize = lt.read(bbuf, 20); Serial.print ("RAW packetSize ="); Serial.println(packetSize); if ((packetSize>1)&&(packetSize<20))

{ digitalWrite(LED_BUILTIN, LOW); // Turn the LED off by making the voltage HIGH delay(2); digitalWrite(LED_BUILTIN, HIGH); // Turn the LED off by making the voltage HIGH

    Serial.println();
   // Serial.println("Packet read OK");
    uint16_t value = lt.getChannel();
    Serial.print ("Current channel = ");
    Serial.println (value);
    Serial.print("Size of packet = ");
    Serial.print(packetSize);
    Serial.println();

    //dump the packet.

    for(int i = 0; i < packetSize; i++)
    {
      if (i) Serial.write(':');
      if (bbuf[i] < 16) Serial.write('0');
      Serial.print(bbuf[i],HEX);

    Serial.println();
   // Serial.write(bbuf,packetSize);
  }

return bbuf[packetSize]; //crc=calc_crc(bbuf,packetSize); }

void setup_wifi() {

delay(4); // We start by connecting to a WiFi network Serial.println(); Serial.print("Connecting to "); Serial.println(ssid);

WiFi.begin(ssid, pass);

while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); }

void setup() { // put your setup code here, to run once: pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output digitalWrite(LED_BUILTIN, HIGH); Serial.begin(256000); Serial.println(F("\n\nLT8900 module sample, v0.1.\n\n"));

SPI.begin(); SPI.setFrequency(1000000);

lt.begin(); lt.setCurrentControl(12,7);

char sbuf[32];

//verify chip registers. for (int i = 0; i <= 50; i++) { uint16_t value = lt.readRegister(i);

sprintf_P(sbuf, PSTR("%d = %04x\r\n"), i, value);
Serial.print(sbuf);

} Serial.println(F("Reader mode")); lt.startListening(); lt.whatsUp(Serial); Serial.println(F("Boot completed.")); setup_wifi(); }

void loop() {

lt.setSyncWord(0x55AA00000000050A);
lt.setSyncWordLength(0x01);
lt.setChannel(0x27); //39
lt.startListening();
if (lt.available())
{
 bufer=recieve_code();

lt.setSyncWord(0x1809000000007236); lt.setSyncWordLength(0x11); lt.setChannel(0x08); //39 lt.startListening(); if (lt.available()) { bufer=recieve_code();

lt.setSyncWord(0xBCCD000000009AAB);
lt.setSyncWordLength(0x11);
lt.setChannel(0x03); //3
lt.startListening();
if (lt.available())
{
 bufer=recieve_code();
/// uint8_t crc=calc_crc(bbuf,packetSize);
}

lt.setSyncWord(0xBCCD000000009AAB);
lt.setSyncWordLength(0x11);
lt.setChannel(0x26); //3
lt.startListening();
if (lt.available())
{
 bufer=recieve_code();
}

lt.setSyncWord(0xBCCD000000009AAB);

lt.setSyncWordLength(0x11); lt.setChannel(0x49); //3 lt.startListening(); if (lt.available()) { bufer=recieve_code(); }

lt.setSyncWord(0x03805A5A03800380);
lt.setSyncWordLength(0x10);
lt.setChannel(0x05); //5
lt.startListening();

// lt.whatsUp(Serial); if (lt.available()) { bufer=recieve_code(); lt.whatsUp(Serial);

} 

}

itProfi commented 7 years ago

That's all code.

sidoh commented 7 years ago

Gotcha. Makes sense. Nice to not need to deal with CRC and bit fiddling. But given that it's all handled in a pretty reliable way (thanks to Henryk), I'm not sure it makes sense to switch, especially since it seems like the NRF24L01 is a more popular xceiver.

WoodsterDK commented 7 years ago

Hi there, super work decoding the protocol. I also use the different transciever, and have had quite a few problems with the nRF ones. With some minor tweaks and the addition of two files + a interface selection it should be doable without much hassle. It will only be the transport layer, all the magic happens in your layer.

sidoh commented 7 years ago

Interesting. I've not noticed anything funky with the nrf24s. Do you mind sharing what kinds of issues you saw?

Yeah, I'd imagine it's possible to construct a different implementation of MiLightRadio within MiLightClient and it'd work pretty seamlessly.

I ordered some of these things a few days ago, but they probably won't be here for a few weeks. I can play around with it then.

Obviously happy to look at a PR before then.

WoodsterDK commented 7 years ago

Yeah, instability and quite slow. I had to implement synced fading and control between different groups, and due to all the recalcs of parameters it never looked visually good. With the other module - once set up for a type with the matching sync word, it is just a matter of sending a frame, and the channel is just a register to set also.

sidoh commented 7 years ago

Aah, interesting. Yeah I'm not doing anything that requires nearly that level of precision or performance.

Definitely sounds like it's worth investigating. :)

WoodsterDK commented 7 years ago

I looked at the project, and thought about making a copy of PL1167_nRF24.cpp and make a PL1167_PL8900.cpp leaving the unnecessary functions empty making it compatible with the milightclient.... but it seems the RF24 is well incorporated.... maybe it is better to make a clone of the milightclient, accessing the new module directly, and then differ when init the client module.

itProfi commented 7 years ago

I looked at the project, and thought about making a copy of PL1167_nRF24.cpp and make a PL1167_PL8900.cpp leaving the unnecessary functions empty making it compatible with the milightclient.... but it seems the RF24 is well incorporated.... maybe it is better to make a clone of the milightclient, accessing the new module directly, and then differ when init the client module.

If need, i can be a tester with LT8900 or LT8920..:)

sidoh commented 7 years ago

I feel like MiLightRadio is the right layer of abstraction here. I guess it seems like exactly the interface for the "transport layer" you referred to above. Without knowing exactly what you'll need to do, the methods in this class seem more or less exactly what you what to swap implementations for:

    int begin();
    bool available();
    int read(uint8_t frame[], size_t &frame_length);
    int dupesReceived();
    int write(uint8_t frame[], size_t frame_length);
    int resend();
    int configure();

Obviously some things like the reference to an AbstractPL1167 would need to be pulled into a separate implementation (something like NrfMiLightRadio, maybe?)

Then it'd just be a matter of passing or constructing a different type of MiLightRadio in MiLightClient.

WoodsterDK commented 7 years ago

I think the AbstractPL1167 can be omitted, and then there must be added to RadioStack also.

sidoh commented 7 years ago

RadioStack is just meant to be pairs of MiLightRadio and MiLightRadioConfig. I think stuff specific to the NRF would be pulled into the NRF-specific implementation of MiLightRadio.

The interfaces are messy and bleed into each other because the transport layer wasn't an important abstraction. Obviously we'd want to clean that up before adding a new impl. :)

Let me know if I can help out making the code more amenable to this.

WoodsterDK commented 7 years ago

I will try to make a mockup, and then you can come with some inputs afterwards.

WoodsterDK commented 7 years ago

Just an update - I can receive something, but will just tidy up the code... hopefully something within a day or two

sidoh commented 7 years ago

Awesome :)

WoodsterDK commented 7 years ago

There might be added a further pin setup for a hardware reset pin - if set to '0' then it is not used. Furthermore a setup of RF module used: nRF or LT8900 compatible...

WoodsterDK commented 7 years ago

I have reception running, and also transmission, one thing though is I have three RGB_CCT bulbs on the same group, and when sending an on/off - one or two does not respond, but then one is reacting as it should. And then the behaviour shuffles between the bulbs.... it is late here - will look into it the next few days.

WoodsterDK commented 7 years ago

Might be some timing issues caused by the stream and my resend function... can be sortes.

sidoh commented 7 years ago

Awesome! I'm excited to test this out. I noticed yesterday while testing some of the UDP changes that something seems pretty sluggish, and I'm wondering if it's the NRF. Could totally be my rather unoptimized UDP handling too, but one can hope :)

WoodsterDK commented 7 years ago

Have you tried multiple RGB_CCT bulbs in a group with the nRF interface.... do they all respond as they should - I keep getting the same issue, where they shuffle in the behaviour? What about the frame that is being sent when powering the remotes, could that be a "MASTER" frame the resets the bulbs sequence number, to make them listen again for a low sequence number? Do they respond, if the number decrement instead of increment?

sidoh commented 7 years ago

Yeah, I have three different groups of RGB+CCT bulbs I've been using. Two of them have three bulbs, the other has two. They all at least appear to act in unison. It's definitely necessary to send repeat packets. I'm sending 30-50 on each channel the bulbs listen on. This might be excessive, but I've found that it's a good balance of responsiveness and reliability.

Bulbs do seem to ignore packets that have the same sequence value as the last packet they saw. I noticed this when replaying packets. I haven't tried sending packets with decreasing sequence numbers. My remotes and wifi box definitely seem to send packets with increasing sequence values.

As far as I've been able to tell, official devices are only sending the same packet multiple times per action, and not multiple packets.

WoodsterDK commented 7 years ago

For best result on the other bulbs I've used around 100 transmissions spread across all channels. I've just switched to the v1.1.0 branch - but now PlatformIO is acting up.... doh. It might be the sequence number just needs to be different from command to command, to prevent acting many times on the re-transmits.

sidoh commented 7 years ago

Gotcha, interesting. I suppose it depends a bit on timing and signal strength?

What's PlatformIO doing? Hope I didn't break something. :(

Right, makes sense that it'd only need to be different. Only meant to suggest that the official devices seem to increment the sequence number by one rather than changing it by some other function.

WoodsterDK commented 7 years ago

PlatformIO is running again with latest v1.1.0 - but still the same. I can pair all three bulbs with the gateway, but they actually flashed green out of sync, and if I sync with a real remote, they pair and flash green in sync.... so something is off when transmitting the frames. Reception works super, but just the problem with transmission. What can it be......they change pattern on pressing the on toggle switch on the web interface. But the encrypted frame must be OK, as some of the bulbs react. Can it be related to the switch between channels..... or.... well. Night time here... .I'm off to bed.

WoodsterDK commented 7 years ago

Problem solved:) - stupid mistake with an internal value being used instead of the right one - will clean up the code, and try to make a way to switch between the two interfaces.

WoodsterDK commented 7 years ago

An option to select different modules must be added, but what about showing the connection state to the module on the web app. Makes it easy to identify if everything is connected OK.

itProfi commented 7 years ago

Where try new code? :)

WoodsterDK commented 7 years ago

Will see if I can get it done later tonight..

sidoh commented 7 years ago

Awesome! Was it was performant as you hoped?

sidoh commented 7 years ago

Settings is where we'd put a setting to swap between radio modules, btw.

WoodsterDK commented 7 years ago

Yep - working on it.... due to heavy work activity it might take a day or two - sorry. Will try to make it as fast as possible, or at least upload something nearly finished.

WoodsterDK commented 7 years ago

How will you prefer to get the changes...?

sidoh commented 7 years ago

Pull request sounds good to me if that works for you.

Should probably start a new minor release branch for it (v1.2.0).

WoodsterDK commented 7 years ago

OK - I will make a branch v1.2.0 in my fork, commit the changes, and see if I can get the pull to work. Might get the time later today.

itProfi commented 7 years ago

OK - I will make a branch v1.2.0 in my fork, commit the changes, and see if I can get the pull to work. Might get the time later today.

Can you say pinout by default for LT8900 (in your version)?

WoodsterDK commented 7 years ago

I use cs 15 and pin 4, reset is not used

WoodsterDK commented 7 years ago

But you can set it from the web app

itProfi commented 7 years ago

Like this: image

Reset not used (on LT8900) Whats about PKT?

WoodsterDK commented 7 years ago

Pkt shares the setting with csne, and you can connect reset also just assign a value different than 0 in the web app.

WoodsterDK commented 7 years ago

Pkt is used as rx frame ready detection

WoodsterDK commented 7 years ago

From my fork you just cannot save the module type yet. I saw somewhere that sidoh mentioned a rewrite, so thought is was more fun if you could test it.

itProfi commented 7 years ago

image I propose correct this lablel to PL1167/LT8900/8910/8920

itProfi commented 7 years ago

Pkt shares the setting with csne

You mean csn_pin?

WoodsterDK commented 7 years ago

Makes sense with the label☺ Yes sorry, the csn pin.

sidoh commented 7 years ago

From my fork you just cannot save the module type yet. I saw somewhere that sidoh mentioned a rewrite, so thought is was more fun if you could test it.

Rewrite of the web app? Yeah, made #23 for that. Not sure when I'll get around to that, though.