/* Ansulta Control with NodeMCU and CC2500 created 24.11.2018 by matlen67 Hardware: * NodeMCU Lolin V3 (az-delivery) * CC2500 (WLC240) (ebay) Wired: NodeMCU CC2500 SPI GPIO Board ---------------------- -------- SLC GPIO14 (D5) SCLK MISO GPIO12 (D6) MISO MOSI GPIO13 (D7) MOSI CSx GPIO15 (D8) CSN */ #include "cc2500_REG.h" #include "cc2500_VAL.h" #include "cc2500_CMD.h" #include #include #define CS 15 // ChipSelect NodeMCU Pin15 #define Light_OFF 0x01 // Command to turn the light off #define Light_ON_50 0x02 // Command to turn the light on 50% #define Light_ON_100 0x03 // Command to turn the light on 100% #define Light_PAIR 0xFF // Command to pair a remote to the light const boolean DEBUG = false; // debug mode print same infos by RS232 const char* ssid = "here your SSID"; const char* password = "here your Wlankey"; WiFiServer server(80); String header; /* get your ansluta address! ------------------------- connect browser to webcontrol example: 192.168.178.130/ansluta/getAddress press button within 5 sec on your original ansluta remote is a valid address detect it will be displayed */ // pute here your AddressBytes byte AddressByteA = 0xD0; byte AddressByteB = 0x9A; void setup(){ // config ChipSelect pinMode(CS,OUTPUT); if(DEBUG){ Serial.begin(115200); Serial.println("Debug mode"); Serial.print("Initialisation"); } // Connect to Wi-Fi network with SSID and password if(DEBUG){ Serial.print("Connecting to "); Serial.println(ssid); } WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); if(DEBUG){ Serial.print("."); } } // Print local IP address and start web server if(DEBUG){ Serial.println(""); Serial.println("WiFi connected."); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } server.begin(); // SPI config SPI.begin(); SPI.setDataMode(SPI_MODE0); SPI.setBitOrder(MSBFIRST); SPI.setClockDivider(SPI_CLOCK_DIV64); digitalWrite(CS,HIGH); SendStrobe(CC2500_SRES); //0x30 SRES Reset chip. init_CC2500(); // SendStrobe(CC2500_SPWD); //Enter power down mode - Not used in the prototype WriteReg(0x3E,0xFF); //Maximum transmit power - write 0xFF to 0x3E (PATABLE) if(DEBUG){ Serial.println(" - Done"); } // end setup } void loop(){ WiFiClient client = server.available(); // Listen for incoming clients if (client) { // If a new client connects, if(DEBUG){ Serial.println("New Client."); // print a message out in the serial port } String currentLine = ""; // make a String to hold incoming data from the client String adrByte = ""; boolean adrState = false; int timeOut = 0; while (client.connected()) { // loop while the client's connected timeOut ++; if (timeOut >= 500000){ // dirty workaround because ClientTimeout not Work! client.stop(); // Chrome keep alive the connection and block other connection (Fhem,Firefox) } if (client.available()) { // if there's bytes to read from the client, char c = client.read(); // read a byte, then if(DEBUG){ Serial.write(c); // print it out the serial monitor } header += c; if (c == '\n') { // if the byte is a newline character // if the current line is blank, you got two newline characters in a row. // that's the end of the client HTTP request, so send a response: if (currentLine.length() == 0) { // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) // and a content-type so the client knows what's coming, then a blank line: client.println("HTTP/1.1 200 OK"); client.println("Content-type:text/html"); client.println("Connection: close"); client.println(); // Display the HTML web page client.println(""); client.println(""); client.println(""); // CSS to style the on/off buttons // Feel free to change the background-color and font-size attributes to fit your preferences client.println(""); // Web Page Heading client.println("

-- NodeMCU --

"); client.println("

Ansluta Control

"); // turn the light on/off if (header.indexOf("GET /ansluta/50") >= 0) { if(DEBUG){ Serial.println("Ansluta 50% "); } SendCommand(AddressByteA,AddressByteB, Light_ON_50); } else if (header.indexOf("GET /ansluta/100") >= 0) { if(DEBUG){ Serial.println("Ansluta 100%"); } SendCommand(AddressByteA,AddressByteB, Light_ON_100); } else if (header.indexOf("GET /ansluta/0") >= 0) { if(DEBUG){ Serial.println("Ansluta 0%"); } SendCommand(AddressByteA,AddressByteB, Light_OFF); } else if (header.indexOf("GET /ansluta/getAddress") >= 0) { if(DEBUG){ Serial.println("Ansluta getAddress"); } adrState = true; client.println("
"); client.println("

Listen for adressbyte...

"); client.println("

Press button on original remote!

"); //client.println(""); client.println(); delay(10); client.flush(); //client.stop(); adrByte = ReadAddressBytes(); } if(adrState == false){ client.println("
"); client.println("

"); client.println("

"); client.println("
"); client.println("

"); client.println("

"); client.println("
"); client.println("

"); client.println("

"); }else{ client.println("
"); client.println("

Your Ansluta address: " + adrByte + "

"); adrState = false; adrByte = ""; } client.println(""); // The HTTP response ends with another blank line client.println(); // Break out of the while loop break; } else { // if you got a newline, then clear currentLine currentLine = ""; } } else if (c != '\r') { // if you got anything else but a carriage return character, currentLine += c; // add it to the end of the currentLine } } } // Clear the header variable header = ""; // Close the connection //delay(1); client.stop(); if(DEBUG){ Serial.println("Client disconnected."); Serial.println(""); } } } String ReadAddressBytes(){ //Read Address Bytes From a remote by sniffing its packets wireless byte tries=0; boolean AddressFound = false; String A = ""; String B = ""; if(DEBUG){ Serial.print("Listening for an Address"); } while((tries<200)&&(!AddressFound)){ SendStrobe(CC2500_SRX); // 0x34 Enable RX. WriteReg(REG_IOCFG1,0x01); // REG_IOCFG1 = 0x01 Switch MISO to output if a packet has been received or not delay(20); byte PacketLength = ReadReg(CC2500_FIFO); byte recvPacket[PacketLength]; if ( PacketLength >= 1) { if(DEBUG){ Serial.println(); Serial.print("Packet received: "); Serial.print(PacketLength,DEC); Serial.println(" bytes"); } if(PacketLength <= 8) { //A packet from the remote cant be longer than 8 bytes for(byte i = 1; i <= PacketLength; i++){ //Read the received data from CC2500 recvPacket[i] = ReadReg(CC2500_FIFO); if(DEBUG){ if(recvPacket[i]<0x10){Serial.print("0");} Serial.print(recvPacket[i],HEX); } } if(DEBUG){ Serial.println(); } } byte start=0; while((recvPacket[start]!=0x55) && (start < PacketLength)){ //Search for the start of the sequence start++; } if(recvPacket[start+1]==0x01 && recvPacket[start+5]==0xAA){ //If the bytes match an Ikea remote sequence AddressFound = true; AddressByteA = recvPacket[start+2]; // Extract the addressbytes AddressByteB = recvPacket[start+3]; if(DEBUG){ Serial.print("Address Bytes found: "); if(AddressByteA<0x10){Serial.print("0");} Serial.print(AddressByteA,HEX); if(AddressByteB<0x10){Serial.print("0");} Serial.println(AddressByteB,HEX); } if(AddressByteA<0x10){A = "0";} A += String(AddressByteA,HEX); if(AddressByteA<0x10){B = "0";} B += String(AddressByteB,HEX); return A + B; } SendStrobe(CC2500_SIDLE); // Exit RX / TX SendStrobe(CC2500_SFRX); // Flush the RX FIFO buffer } tries++; } if(DEBUG){ Serial.println(" - Done"); } return ""; } byte ReadReg(byte addr){ addr = addr + 0x80; // set r/w bit (bit7=1 read, bit7=0 write) digitalWrite(CS,LOW); delayMicroseconds(1); // can't wait for digitalRead(MISO)==HIGH! Don't work in SPI mode byte x = SPI.transfer(addr); delay(10); byte y = SPI.transfer(0); delayMicroseconds(1); digitalWrite(CS,HIGH); return y; } void SendStrobe(byte strobe){ digitalWrite(CS,LOW); delayMicroseconds(1); // can't wait for digitalRead(MISO)==HIGH! Don't work in SPI mode SPI.write(strobe); digitalWrite(CS,HIGH); delayMicroseconds(2); } void SendCommand(byte AddressByteA, byte AddressByteB, byte Command){ for(byte i=0;i<50;i++){ //Send 50 times SendStrobe(CC2500_SFTX); // 0x3B SendStrobe(CC2500_SIDLE); // 0x36 digitalWrite(CS,LOW); delayMicroseconds(1); // can't wait for digitalRead(MISO)==HIGH! Don't work in SPI mode SPI.transfer(0x7F); // activate burst data delayMicroseconds(2); SPI.transfer(0x06); // send 6 data bytes delayMicroseconds(2); SPI.transfer(0x55); // ansluta data byte 1 delayMicroseconds(2); SPI.transfer(0x01); // ansluta data byte 2 delayMicroseconds(2); SPI.transfer(AddressByteA); // ansluta data address byte A delayMicroseconds(2); SPI.transfer(AddressByteB); // ansluta data address byte B delayMicroseconds(2); SPI.transfer(Command); // ansluta data command 0x01=Light OFF 0x02=50% 0x03=100% 0xFF=Pairing delayMicroseconds(2); SPI.transfer(0xAA); // ansluta data byte 6 delayMicroseconds(2); digitalWrite(CS,HIGH); // end transfer SendStrobe(CC2500_STX); // 0x35 transmit data in TX delayMicroseconds(1600); } //delay(20); //SendStrobe(CC2500_SPWD); // 0x39 cc2500 sleep //delayMicroseconds(2); } void WriteReg(byte addr, byte value){ digitalWrite(CS,LOW); delayMicroseconds(1); // can't wait for digitalRead(MISO)==HIGH! Don't work in SPI mode SPI.transfer(addr); delayMicroseconds(1); SPI.transfer(value); delayMicroseconds(1); digitalWrite(CS,HIGH); } void init_CC2500(){ WriteReg(REG_IOCFG2,VAL_IOCFG2); WriteReg(REG_IOCFG0,VAL_IOCFG0); WriteReg(REG_PKTLEN,VAL_PKTLEN); WriteReg(REG_PKTCTRL1,VAL_PKTCTRL1); WriteReg(REG_PKTCTRL0,VAL_PKTCTRL0); WriteReg(REG_ADDR,VAL_ADDR); WriteReg(REG_CHANNR,VAL_CHANNR); WriteReg(REG_FSCTRL1,VAL_FSCTRL1); WriteReg(REG_FSCTRL0,VAL_FSCTRL0); WriteReg(REG_FREQ2,VAL_FREQ2); WriteReg(REG_FREQ1,VAL_FREQ1); WriteReg(REG_FREQ0,VAL_FREQ0); WriteReg(REG_MDMCFG4,VAL_MDMCFG4); WriteReg(REG_MDMCFG3,VAL_MDMCFG3); WriteReg(REG_MDMCFG2,VAL_MDMCFG2); WriteReg(REG_MDMCFG1,VAL_MDMCFG1); WriteReg(REG_MDMCFG0,VAL_MDMCFG0); WriteReg(REG_DEVIATN,VAL_DEVIATN); WriteReg(REG_MCSM2,VAL_MCSM2); WriteReg(REG_MCSM1,VAL_MCSM1); WriteReg(REG_MCSM0,VAL_MCSM0); WriteReg(REG_FOCCFG,VAL_FOCCFG); WriteReg(REG_BSCFG,VAL_BSCFG); WriteReg(REG_AGCCTRL2,VAL_AGCCTRL2); WriteReg(REG_AGCCTRL1,VAL_AGCCTRL1); WriteReg(REG_AGCCTRL0,VAL_AGCCTRL0); WriteReg(REG_WOREVT1,VAL_WOREVT1); WriteReg(REG_WOREVT0,VAL_WOREVT0); WriteReg(REG_WORCTRL,VAL_WORCTRL); WriteReg(REG_FREND1,VAL_FREND1); WriteReg(REG_FREND0,VAL_FREND0); WriteReg(REG_FSCAL3,VAL_FSCAL3); WriteReg(REG_FSCAL2,VAL_FSCAL2); WriteReg(REG_FSCAL1,VAL_FSCAL1); WriteReg(REG_FSCAL0,VAL_FSCAL0); WriteReg(REG_RCCTRL1,VAL_RCCTRL1); WriteReg(REG_RCCTRL0,VAL_RCCTRL0); WriteReg(REG_FSTEST,VAL_FSTEST); WriteReg(REG_TEST2,VAL_TEST2); WriteReg(REG_TEST1,VAL_TEST1); WriteReg(REG_TEST0,VAL_TEST0); WriteReg(REG_DAFUQ,VAL_DAFUQ); }