• 10 dec 2017: forum version update. In case of issues use this topic.
  • 30 nov 2017: pilight moved servers. In case of issues use this topic.
Hello There, Guest! Login Register


Kambrook
#1
Hi All,

I stumbled upon pilight a couple of days ago and decided to create a protocol for the Kambrook wireless powerpoints that are readily available here in Australia. I decoded the protocol myself using the debug command but later found that it had already been done for another project (http://wiki.beyondlogic.org/index.php?ti...Controller)

pilight now is able to control my lights with commands like the following:
Code:
sudo pilight-send -p kambrook -i 12058 -u 2 -t


and it registers on the receiver program as:
Code:
{
    "origin": "sender",
    "protocol": "kambrook",
    "code": {
        "id": 12058,
        "unit": 2,
        "state": "on"
    },
    "repeat": 1,
    "uuid": "0000-00-00-7e-68f702"
}

However I find it impossible to get the configuration part working, which is now stripped right back to basics (see below). When I try to run the daemon with my config loaded I get the error:
Code:
pilight-daemon: ERROR: setting #3 "id" of "floorlamp", invalid

However, if I replace "kambrook" with "kaku_switch" it loads correctly (but obviously doesn't work with my switches).

Code:
{
        "study": {
                "name": "Study",
                "floorlamp": {
                        "name": "Floor Lamp",
                        "protocol": [ "kambrook" ],
                        "id": [{
                                "id": 120,
                                "unit": 1
                        }],
                        "state": "on"
                }
        }
}

Just in case you need the extra information, here is the protocol code:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "../../pilight.h"
#include "common.h"
#include "dso.h"
#include "log.h"
#include "protocol.h"
#include "hardware.h"
#include "binary.h"
#include "gc.h"
#include "kambrook.h"




static void kambrookCreateMessage(int id, int unit, int state) {
        kambrook->message = json_mkobject();
        json_append_member(kambrook->message, "id", json_mknumber(id));
        json_append_member(kambrook->message, "unit", json_mknumber(unit));
        if(state == 0) {
                json_append_member(kambrook->message, "state", json_mkstring("on"));
        } else {
                json_append_member(kambrook->message, "state", json_mkstring("off"));
        }
}

static void kambrookCreateLow(int s, int e) {
        int i;

        for(i=s;i<=e;i+=2) {
                kambrook->raw[i]=(kambrook->plslen->length);
                kambrook->raw[i+1]=(kambrook->plslen->length);
        }
}


static void kambrookCreateHigh(int s, int e) {
        int i;

        for(i=s;i<=e;i+=2) {
                kambrook->raw[i]=(kambrook->pulse*kambrook->plslen->length);
                kambrook->raw[i+1]=(kambrook->plslen->length);
        }
}

static void kambrookCreateHeader(void){
        int i;
        for(i=2;i<16;i+=4) {
                kambrookCreateHigh(i,i+1);
        }
}

static void kambrookCreateSystemCode(int id) {
        int binary[255];
        int length = 0;
        int i=0, x=0;

        length = decToBinRev(id, binary);
        for(i=0;i<=length;i++) {
                if(binary[i]==1) {
                        x=i*2;
                        kambrookCreateHigh(62-x,62-x+1);
                }
        }
}

static void kambrookClearCode(void) {
        kambrookCreateLow(0,94);
}


static void kambrookCreateFooter(void) {
        kambrookCreateHigh(80,94);
        kambrook->raw[95]=(PULSE_DIV*kambrook->plslen->length);
}

static void kambrookCreateOverallCode(int unit, int state) {
        int binary[255];
        int length = 0;
        int i=0, x=0;
        int overallcode=0;

        while(unit>5) {
                overallcode+=16;
                unit-=5;
        }
        overallcode+=(unit*2)-1+state;

        length = decToBinRev(overallcode, binary);
        for(i=0;i<=length;i++) {
                if(binary[i]==1) {
                        x=i*2;
                        kambrookCreateHigh(78-x, 78-x+1);
                }
        }
}

static int kambrookCreateCode(JsonNode *code) {
        int id = -1;
        int unit = -1;
        int state = -1;
        double itmp = 0;

        if(json_find_number(code, "id", &itmp) == 0)
                id = (int)round(itmp);
        if(json_find_number(code, "unit", &itmp) == 0)
                unit = (int)round(itmp);
        if(json_find_number(code, "off", &itmp) == 0)
                state=1;
        else if(json_find_number(code, "on", &itmp) == 0)
                state=0;

        if(id == -1 || unit == -1 || state == -1) {
                logprintf(LOG_ERR, "kambrook: insufficient number of arguments");
                return EXIT_FAILURE;
        } else if(id > 65535 || id < 1) {
                logprintf(LOG_ERR, "kambrook: invalid id range");
                return EXIT_FAILURE;
        } else if(unit > 20 || unit < 1) {
                logprintf(LOG_ERR, "kambrook: invalid unit range");
                return EXIT_FAILURE;
        } else {
                kambrookCreateMessage(id, unit, state);
                kambrookClearCode();
                kambrookCreateHeader();
                kambrookCreateSystemCode(id);
                kambrookCreateOverallCode(unit,state);
                kambrookCreateFooter();
        }
        return EXIT_SUCCESS;
}

static void kambrookPrintHelp(void) {
        printf("\t -i --id=id\tcontrol a device with this id (systemcode) (1-32755)\n");
        printf("\t -u --unit=unit\t\tcontrol a device with this unit (1-20)\n");
        printf("\t -t --on\t\t\tsend an on signal\n");
        printf("\t -f --off\t\t\tsend an off signal\n");}

#ifndef MODULE
__attribute__((weak))
#endif
void kambrookInit(void) {
    protocol_register(&kambrook);
    protocol_set_id(kambrook, "kambrook");
    protocol_device_add(kambrook, "kambrook", "Kambrook Powerpoint protocol");
        protocol_plslen_add(kambrook, 298);
        kambrook->devtype = SWITCH;
        kambrook->hwtype = RF433;
        kambrook->pulse = 2;
        kambrook->rawlen = 96;
        kambrook->binlen = 48;

        options_add(&kambrook->options, 'i', "id", OPTION_HAS_VALUE, CONFIG_ID, JSON_NUMBER, NULL, "^[0-9]+$");
        options_add(&kambrook->options, 'u', "unit", OPTION_HAS_VALUE, CONFIG_ID, JSON_NUMBER, NULL, "^([0-9]{2})$");
        options_add(&kambrook->options, 't', "on", OPTION_NO_VALUE, CONFIG_STATE, JSON_STRING, NULL, NULL);
        options_add(&kambrook->options, 'f', "off", OPTION_NO_VALUE, CONFIG_STATE, JSON_STRING, NULL, NULL);

        options_add(&kambrook->options, 0, "gui-readonly", OPTION_HAS_VALUE, CONFIG_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");

        kambrook->createCode=&kambrookCreateCode;
        kambrook->printHelp=&kambrookPrintHelp;
}

#ifdef MODULE
void compatibility(struct module_t *module) {
    module->name = "kambrook";
    module->version = "0.1";
    module->reqversion = "5.0";
    module->reqcommit = NULL;
}

void init(void) {
    kambrookInit();
}

#endif


Any help would be great, I feel that I am so close!

Cheers and great software (I will re-comment when I get it working).

Kade (edak)
 
Reply
#2
Can you rewrite the protocol to it will work on the nightly (future) version.

The issue is the regex of the unit code. It tells pilight it MUST contain 2 numbers.
 
Reply
#3
Hey Curlymo,

Thank you very much for the advice, I have been pulling my hair out over this and would never have thought it was the regex expression as the commandline arguments worked with only one digit instead of two. It now starts up and loads the configuration successfully but still seems to have an issue sending the command?

If I send via command line I get this in the debug:
Code:
[Dec 11 13:15:57:653508] pilight-daemon: DEBUG: **** RAW CODE ****
298 298 596 298 298 298 596 298 298 298 596 298 298 298 596 298 298 298 298 298 298 298 298 298 298 298 298 298 298 298 298 298 298 298 298 298 596 298 298 298 596 298 596 298 596 298 596 298 298 298 298 298 298 298 596 298 596 298 298 298 596 298 298 298 298 298 298 298 298 298 298 298 298 298 596 298 298 298 298 298 596 298 596 298 596 298 596 298 596 298 596 298 596 298 596 10132
[Dec 11 13:15:57:654052] pilight-daemon: DEBUG: **** RAW CODE ****
[Dec 11 13:15:58:126118] pilight-daemon: DEBUG: successfully send kambrook code
[Dec 11 13:15:58:127786] pilight-daemon: DEBUG: broadcasted: {"origin":"sender","protocol":"kambrook","code":{"id":12058,"unit":2,"state":"off"},"repeat":1,"uuid":"0000-00-00-7e-68f702"}

and if I send via the web interface it does this:
Code:
[ Dec 11 13:16:54:81149] pilight-daemon: DEBUG: **** RAW CODE ****
298 298 596 298 298 298 596 298 298 298 596 298 298 298 596 298 298 298 298 298 298 298 298 298 298 298 298 298 298 298 298 298 298 298 298 298 596 298 298 298 596 298 596 298 596 298 596 298 298 298 298 298 298 298 596 298 596 298 298 298 596 298 298 298 298 298 298 298 298 298 298 298 298 298 596 298 298 298 298 298 596 298 596 298 596 298 596 298 596 298 596 298 596 298 596 10132
[ Dec 11 13:16:54:81682] pilight-daemon: DEBUG: **** RAW CODE ****
[Dec 11 13:16:54:436765] pilight-daemon: INFO: client connected, ip 172.16.1.103, port 50414
[Dec 11 13:16:54:554639] pilight-daemon: DEBUG: successfully send kambrook code
[Dec 11 13:16:54:557514] pilight-daemon: DEBUG: socket write succeeded: {"origin":"config","type":1,"devices":{"study":[ "floorlamp" ]},"values":{"timestamp":1418264214,"state":"off"}}
[Dec 11 13:16:54:560894] pilight-daemon: DEBUG: broadcasted: {"origin":"config","type":1,"devices":{"study":[ "floorlamp" ]},"values":{"timestamp":1418264214,"state":"off"}}

Note that both have the same raw code, but I don't think it's sending anything from the web interface to the hardware level as there's no response whatsoever from the light.

Any ideas?

Great product by the way, it has a lot more WAF (Wife Acceptance Factor) than the other solution that I cobbled up together on my own.
 
Reply
#4
I don't see any meaningfull difference?
 
Reply
#5
Neither had I, however when interacting with the web interface, nothing is transmitted and my lights are not activated, but from the command line they work every time. This might be a bug of some kind? Perhaps it's something else that I have overlooked that links the web/json interface with the hardware itself?
 
Reply
#6
No, but as i said earlier. When you develop new stuff, always use the development version. A lot of bugs are often already solved (that i don't even remember either).
 
Reply
#7
I re-wrote the library for use with the nightly, and installed the nightly (that was a bit of a pain as the dependencies weren't installed - but I found the answer on the forum). After now also re-writing the config file in the new format, I am now in business!

Thank you for your help, I guess I should have started with the dev version to begin with.
SmileSmileSmile

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "../../pilight.h"
#include "common.h"
#include "dso.h"
#include "log.h"
#include "protocol.h"
#include "hardware.h"
#include "binary.h"
#include "gc.h"
#include "kambrook.h"




static void kambrookCreateMessage(int id, int unit, int state) {
        kambrook->message = json_mkobject();
        json_append_member(kambrook->message, "id", json_mknumber(id,0));
        json_append_member(kambrook->message, "unit", json_mknumber(unit,0));
        if(state == 0) {
                json_append_member(kambrook->message, "state", json_mkstring("on"));
        } else {
                json_append_member(kambrook->message, "state", json_mkstring("off"));
        }
}


static void kambrookCreateLow(int s, int e) {
        int i;

        for(i=s;i<=e;i+=2) {
                kambrook->raw[i]=(kambrook->plslen->length);
                kambrook->raw[i+1]=(kambrook->plslen->length);
        }
}


static void kambrookCreateHigh(int s, int e) {
        int i;

        for(i=s;i<=e;i+=2) {
                kambrook->raw[i]=(kambrook->pulse*kambrook->plslen->length);
                kambrook->raw[i+1]=(kambrook->plslen->length);
        }
}

static void kambrookCreateHeader(void){
        int i;
        for(i=2;i<16;i+=4) {
                kambrookCreateHigh(i,i+1);
        }
}

static void kambrookCreateId(int id) {
        int binary[255];
        int length = 0;
        int i=0, x=0;

        length = decToBinRev(id, binary);
    for(i=0;i<=length;i++) {
                if(binary[i]==1) {
                        x=i*2;
                        kambrookCreateHigh(62-x,62-x+1);
                }
        }
}

static void kambrookClearCode(void) {
        kambrookCreateLow(0,94);
}


static void kambrookCreateFooter(void) {
        kambrookCreateHigh(80,94);
        kambrook->raw[95]=(PULSE_DIV*kambrook->plslen->length);
}

static void kambrookCreateOverallCode(int unit, int state) {
        int binary[255];
        int length = 0;
        int i=0, x=0;
    int overallcode=0;

    while(unit>5) {
        overallcode+=16;
        unit-=5;
    }
    overallcode+=(unit*2)-1+state;

        length = decToBinRev(overallcode, binary);
        for(i=0;i<=length;i++) {
                if(binary[i]==1) {
                        x=i*2;
                        kambrookCreateHigh(78-x, 78-x+1);
                }
        }
}


static int kambrookCreateCode(JsonNode *code) {
        int id = -1;
        int unit = -1;
        int state = -1;
        double itmp = 0;

        if(json_find_number(code, "id", &itmp) == 0)
                id = (int)round(itmp);
        if(json_find_number(code, "unit", &itmp) == 0)
                unit = (int)round(itmp);
        if(json_find_number(code, "off", &itmp) == 0)
                state=1;
        else if(json_find_number(code, "on", &itmp) == 0)
                state=0;

        if(id == -1 || unit == -1 || state == -1) {
                logprintf(LOG_ERR, "kambrook: insufficient number of arguments");
                return EXIT_FAILURE;
        } else if(id > 65535 || id < 1) {
                logprintf(LOG_ERR, "kambrook: invalid id range");
                return EXIT_FAILURE;
        } else if(unit > 19 || unit < 1) {
                logprintf(LOG_ERR, "kambrook: invalid unit range");
                return EXIT_FAILURE;
        } else {
                kambrookCreateMessage(id, unit, state);
        kambrookClearCode();
                kambrookCreateHeader();
                kambrookCreateId(id);
                kambrookCreateOverallCode(unit,state);
                kambrookCreateFooter();
        }
        return EXIT_SUCCESS;
}

static void kambrookPrintHelp(void) {
        printf("\t -i --id=id\tcontrol a device with this id (systemcode) (1-29999)\n");
        printf("\t -u --unit=unit\t\tcontrol a device with this unit (1-19)\n");
        printf("\t -t --on\t\t\tsend an on signal\n");
        printf("\t -f --off\t\t\tsend an off signal\n");}

#ifndef MODULE
__attribute__((weak))
#endif
void kambrookInit(void) {
    protocol_register(&kambrook);
    protocol_set_id(kambrook, "kambrook");
    protocol_device_add(kambrook, "kambrook", "Kambrook Powerpoint protocol");
        protocol_plslen_add(kambrook, 298);
        kambrook->devtype = SWITCH;
        kambrook->hwtype = RF433;
        kambrook->pulse = 2;
        kambrook->rawlen = 96;
        kambrook->binlen = 48;

        options_add(&kambrook->options, 'i', "id", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^(([0-2][0-9][0-9][0-9][0-9])|\\d{4}|\\d{3}|\\d{2}|[1-9])$");
        options_add(&kambrook->options, 'u', "unit", OPTION_HAS_VALUE, DEVICES_ID, JSON_NUMBER, NULL, "^([0-1]?[0-9])$");
        options_add(&kambrook->options, 't', "on", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);
        options_add(&kambrook->options, 'f', "off", OPTION_NO_VALUE, DEVICES_STATE, JSON_STRING, NULL, NULL);

        options_add(&kambrook->options, 0, "readonly", OPTION_HAS_VALUE,GUI_SETTING, JSON_NUMBER, (void *)0, "^[10]{1}$");

    kambrook->createCode=&kambrookCreateCode;
        kambrook->printHelp=&kambrookPrintHelp;
}

#ifdef MODULE
void compatibility(struct module_t *module) {
    module->name = "kambrook";
    module->version = "0.1";
    module->reqversion = "5.0";
    module->reqcommit = NULL;
}

void init(void) {
    kambrookInit();
}

#endif
 
Reply
#8
Last step would be reading how to do a pull-request. Then you name will show up as a contributer. Also don't forget to include the header with your and my name Smile
 
Reply
#9
I have little idea about doing pull requests into github, however I gave it a go, I guess I will see if it worked?
 
Reply
#10
I should get an email when someone does a PR, haven't seen one Smile
 
Reply
  


Forum Jump:


Browsing: 1 Guest(s)