Announcement

Collapse
No announcement yet.

Creating new components?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Creating new components?

    Hi,

    I'm rebuilding my home control system using HS3 and have discovered hsmetro, which looks to be a wonderful interface to use with basic tablets as touchscreens.

    I am trying to get my head around how components function and how to create my own...

    I am a professional programmer but using C and assembly language in such as embedded devices and industrial automation, my experience with javascript is fairly minimal, just self contained fragments I've used in web pages.


    I'm trying to get a weather component working to pick up its data from the WeatherXml plugin, as that seems to work well in itself - but I'm struggling to get it to do anything sensible...

    I have based it on the thermostat module as that reads child devices.
    It's named hsweather to avoid conflicts with existing components.


    It is getting as far as reading the master device and querychild() is being called for each sub-device in the list - but it never executes past the line

    return Promise.resolve(controller.query(query)).then(function (data) {
    in querychild().

    The ip address and device references it's using in the query are correct.



    The following part in querychild is then supposed to allocate data from each child device to the appropriate field - the references are not fixed as with thermostats so the name comparison is required.
    It's never getting that far though.


    I'm using chrome's built in debugger and doing a cache clear refresh after every edit.

    If anyone more familiar with javascript and especially knockout and the other libraries used in hsmetro can have a look, I'd appreciate it!

    Thanks, Rob.


    Code:
    define(['jquery', 'knockout', 'devicecontroller', 'config', 'bluebird', 'text!./hsweather.html', 'underscore', 'faye'], function ($, ko, controller, config, Promise, templateMarkup) {
    
        function Hsweather(params) {
            var self = this;
            var refreshInterval = 300000 //time is in milliseconds.  Currently set to 5 minutes
            var unit = "";
            var proxyPort = config.proxyPort;
            var proxyIP = config.proxyIP;
    
            self.url = config.url;
    
            self.ref = params.ref;
            self.location = params.location;
            self.locstring = params.location + " ";
    
            self.device = ko.observable();
            self.image=ko.observable();
            self.status=ko.observable();
            self.temp=ko.observable();
            self.units=ko.observable();
            self.currently=ko.observable();
            self.city=ko.observable();
            self.windDirection=ko.observable();
            self.windSpeed=ko.observable();
            self.humidity=ko.observable();
            self.description=ko.observable();
            self.forecast=ko.observableArray()();
    
            self.classInfo = ko.observable();
            if (params.hasOwnProperty("color")) {
                self.defaultColor = params.color;
            } else self.defaultColor = "bg-steel";
            self.classInfo("tile tile-wide-x fg-white " + self.defaultColor);
    
            self.locationIsVisible=ko.observable();
            if (params.hasOwnProperty("locationIsVisible")){
                self.locationIsVisible(params.locationIsVisible);
            } else self.locationIsVisible(true); 
    
    
            //FUNCTION queryweather
            var queryweather = function () {
                Promise.resolve(controller.query({
                    "url": self.url,
                    "ref": self.ref,
                    "isParent": true
                })).then(function (data) {
                    self.device(data);
                    //debugger;
    /*
                    if (self.device().statusLabel() == "Offline") {
                        self.setPointIsVisible(false);
                    } else {
                        self.setPointIsVisible(true);
                    }
    */                
                    _.each(self.device().children, function (item) {
                        queryChild(item);
                    });
                })
            }
    
            //FUNCTION queryChild
            var queryChild = function (item) {
                var query = {};
                query.url = self.url;
                query.ref = item;
    
    // OK up to here, URL and item are set
    
                return Promise.resolve(controller.query(query)).then(function (data) {
    
    // A breakpoint here is never triggered - but a breakpoint above the line is.
    
                    self.children.push(data);
                    //debugger;
    
                    var tname = data.devicename;
                    tname = tname.str.replace(self.locstring, '');
    
    
                    if (String(tname).match(/Condition: Icon/)) {
                        // image
                        self.image(self.url + '/images/weatherXML/condition/' + data.string);
                    }
                    else if (String(tname).match(/Temperature/)) {
                        // temp
                        self.temp(data.value);
                    }
                    else if (String(tname).match(/Condition/)) {
                        // currently
                        self.status(data.string);
                    }
                    else if (String(tname).match(/Wind: Direction/)) {
                        // windDirection
                        self.windDirection(data.string);
                    }
                    else if (String(tname).match(/Wind: Speed/)) {
                        // windSpeed
                        self.windSpeed(data.value);
                    }
                    else if (String(tname).match(/Humidity/)) {
                        // humidity
                        self.humidity(data.value);
                    }
                    else {
                        // Not used
                        ;            
                    }
    
                });    
    
            }
    
            queryweather();
    
            //FUNCTION subscribeToProxy
            var subscribeToProxy = function () {
                var proxyURL = "http://" + proxyIP + ":" + proxyPort + "/faye";
                var client = new Faye.Client(proxyURL);
                client.subscribe('/homeseer/statuschange', function (message) {
                    var arr = String(message).split(",");
                    var refID = parseInt(arr[1]);
                    console.log("Proxy Broadcast message received for device: " + arr[1]);
                    //debugger;
                    if (refID == self.setPointControlRef() || refID == self.modeControlRef() ||
                        refID == self.ambientControlRef() || refID == self.humidityControlRef() || refID == self.operatingStatusControlRef() || refID == self.rootControlRef()) {
                        console.log("Proxy Broadcast match--doing query");
                        var q = $.when(queryChild(refID)).done(function (data) {
                            console.log("query complete for refID " + refID);
                            self.pendingIsVisible(false);
                        });
    
                    };
                });
                client.subscribe('/homeseer/hsweather/' + self.ref, function (message) {
                    console.log("Broadcast message received from a hsweather widget");
                    var modeControlRef = message.refID;
                    var setPointControlRef = message.setPointControlRef;
                    if (setPointControlRef == self.setPointControlRef() || modeControlRef == self.modeControlRef()) {
                        console.log("Message ID is a match.  Displaying hourglass");
                        self.pendingIsVisible(message.pendingIsVisible);
                        //self.modeIcon(message.modeIcon);
                        //self.pendingModeValue(message.pendingModeValue);
                        //self.setpoint(message.setpoint);
                        //self.setPointIsVisible(message.setPointIsVisible);
                        //self.controlButtonsAreVisible(message.controlButtonsAreVisible);
                        //self.setPointControlRef(message.setPointControlRef);
                    }
    
                });
            }
    
            var publishToProxy = function (data) {
                var proxyURL = "http://" + proxyIP + ":" + proxyPort + "/faye";
                var client = new Faye.Client(proxyURL);
                var publication = client.publish('/homeseer/hsweather/' + self.ref, data);
                publication.then(function () {
                    console.log('Message received by server!');
                }, function (error) {
                    console.log('Error sending message to proxy server: ' + error.message);
                });
            }
    
            // Check to ensure proxy IP and port values are set.  ThenCreate a new client that subscribes 
            // to the proxy server.  Convert the message to an array
            // and check to ensure the current value isn't equal to the value received from the proxy.
            // If the the value received from the proxy is different then call the function to control the device
            //debugger;
            if (proxyIP && proxyPort) {
                subscribeToProxy();
            }
    
        }
    
    
        // This runs when the component is torn down. Put here any logic necessary to clean up,
        // for example cancelling setTimeouts or disposing Knockout subscriptions/computeds.
        Hsweather.prototype.dispose = function () {};
    
        return {
            viewModel: Hsweather,
            template: templateMarkup
        };
    
    
    });

    For info, a typical child unit response, read directly using a web browser and with some line breaks for legibility around the relevant parts:

    Code:
    {"Name":"HomeSeer Devices","Version":"1.0","Devices":[
    {"ref":423,
    "name":"Worksop Temperature",
    "location":"weatherXML",
    "location2":"weather Conditions",
    "value":5.1,
    "status":"5.1",
    "device_type_string":"weatherXML Location 1",
    "last_change":"\/Date(1576438200950+0000)\/","relationship":4,"hide_from_view":false,"associated_devices":[336],"device_type":{"Device_API":4,"Device_API_Description":"Plug-In API","Device_Type":4,"Device_Type_Description":"Plug-In Type 4","Device_SubType":0,"Device_SubType_Description":""},"device_type_values":null,"UserNote":"","UserAccess":"Any",
    
    "status_image":"/images/weatherXML/thermos/t0s.gif",
    
    "voice_command":"","misc":4352,"interface_name":"weatherXML"}]}
Working...
X