You are reading a single comment by @allObjects and its replies. Click here to read the full conversation.
  • Great description and coding. To recap - in a nutshell:

    1. There are sensor nodes / agents
    2. A sensor node includes / agent handles different types of sensors: temp, ph, ec,...
    3. On (interval) request, the sensor node / agent gets a value from each sensor, sticks them in a readings object and transmits this readings object as JSON over a serial connection to a collector.

    Now, there are some pertinent specifics, such as that:

    • calibrations need to happen before readings can be taken
    • some sensors need other sensor (reading (s) for calibration / calibration which requires a particular sequence by which (some) sensors are operated
    • each type of sensor has a different set or profile of commands to perform its duty.
    • the icing on the cake is that the sensors need some time to process a command -such as for calibration - before a next command can be issued - such get a reading.

    So far so good. - sounds abstract... but most likely not to you sick you touched on all these items in the code (if I'm close).

    2 cents object-oriented analysis and design...

    For each 'thing' (object) in the description we will distill an interface (class, protocol) out of the description. A good techniques is the CRC (index) card analysis, design and validation 'game' to get every thing ready to punch out robust, requirements covering implementation / code (some of that you already have in one form or the other).

    CRC card means to have a card for each 'thing' that names the Class it belongs (the type it is), identifies what all it has to know about itself and what all it has to be able to do - Responsibilities - and whit whom - Collaborators - it needs to work with in order to be able to to fullfill the responsibilities:

    CRC = Class - Responsabilites - Colaborators

    For example, for a 'thing' like me and you, which we call aPerson, because we are an instant (or member) of the Class Person, (basic) Responsibilities are to know first an last name, date of birth (dob), to provide full name - which is first with last name, formal name - which is first's initial and last name, and last but not least, for example, provide / calculate the age in years. For the first four (5) responsibilities we need no other 'thing' - *** Collaborators*** to work with, for the last one though, we need another 'thing', namely aDate thing that knows today's date / year, and that 'thing' is an instance of the Class Date. Noteworthy is that he 'things' we have to know about are already as well instances of Classes, such as aString of String for the name business, and aDate of Date for dob, which both come with responsibilities that come in handy.

    The above text does 'just fine'... but is quite exhausting and not easy to work with on the green table with the business user... therefore the structured CRC index cards, of which we have at least two: one for Class Person and one for Class Date, and for the sake of the game we can also have on for the String class. Luckily, only for the Person class we have to implement, because JavaScript comes with the other two built in - and many more.

    CRC - Class, Responsibilities, Collaborators - cards:
    
    .---------------------------------------­------.
    | Person Class                                |
    |=======================================­======|
    | Responsibilities:          | Collaborators: |
    | - new Person() (create)    |                |
    | - firstname (String)       |                |
    | - lastname (String)        |                |
    | - dateOfBirth (Date)       |                |
    | - getFullName()            |                |
    | - getFormalName()          |                |
    | - getAgeInYears()          | - Date         |
    '---------------------------------------­------'
    
    .---------------------------------------­------.
    | Date Class                                  |
    |=======================================­======|
    | Responsibilities:          | Collaborators: |
    | - new Date() (create today)| (system time)  |
    | - getFullYear()            |                |
    | - ...                      |                |
    '---------------------------------------­------'
    
    .---------------------------------------­------.
    | String Class                                |
    |=======================================­======|
    | Responsibilities:          | Collaborators: |
    | - length                   |                |
    | - charAt(position)         |                |
    | - substr(fromPos, count)   |                |
    | - ...                      |                |
    '---------------------------------------­------'
    

    In an analysis session you sit around the table with empty cards or stand around a flip chart stickies and build together these CRC cards. To verify, run the business use cases / scenarios and each participant holding the card makes sure that responsibilities a fulfillable and collaborators are complete.

    CRC is not really new - actually in IT terms - stony old, but therefore and rock solid AND actual again: agile and CRC. Above cards include already some IT formal notions, such as data types / classes for the state and function parenthesis for behavioral responsibilities, but this can all be done with plain text...

    The Person Class code looks like this:

    //
    // Person class definitions with constructor and methods
    //
    function Person(firstname, lastname, dob) {
      this.firstname = firstname;
      this.lastname = lastname;
      this.dob = dob;
    }
    Person.prototype.getFullName() {
      return this.firstname + " " + this.lastname;
    };
    Person.prototype.getFormalName() {
      return this.firstname + " " + this.lastname;
    };
    Person.prototype.getAgeInYears() {
      return this.dob.getFullYear() - new Date().getFullYear();
    };
    

    Notice the upercase beginning of class names vs. state (variables) and behavior (function) and instances (variable) are - almost - always lower case... This casing makes it very clear from what's a class from which you can make instances with new. To indicate a singletons / 'constant' object / a constant, often all uppercase with underscores is used.

    When you add just one more line to the code above

    exports.Person = Person;
    

    then it is already a complete module - that holds a class definition - and
    you can store it in the modules folder in the sandbox (settings in Web IDE),]
    and you pull it as a module in your application code like this:

    var Person = require("Person");
    

    To save memory and speed up execution, got to google's closure and minifier compiler Web site, paste the code in the left pane, click Compile button, copy-paste the compiled/compressed code from the right pane into a new file which you store in the modules folder in the sandbox named Person.min.js

    function Person(a,b,c){this.firstname=a;this.last­name=b;this.dob=c}Person.prototype.getFu­llName=function(){return this.firstname+" "+this.lastname};Person.prototype.getFor­malName=function(){return this.firstname+" "+this.lastname};Person.prototype.getAge­InYears=function(){return this.dob.getFullYear()-(new Date).getFullYear()};exports.Person=Pers­on;
    

    With his simple piece of code, source code memory saving is about 21%... for complex things the savings are more significant...

    For now, lets just paste the first code block into the source editor / right hand pane of the Espruino Web IDE, add the following lines to crate 'aPerson', upload it and then have some fun with it in the console / left hand pane of the Espruino Web IDE.

    // All Object was born 3/26/1985... wishful thinking... NOTE month is 0..11:
    var person = new Person("All", "Objects", new Date(1985,2,26,));
    

    Work/validate expected behavior of the person in the console with:

    person.lastname;
    person.getFormalName();
    person.getAgeInYears();
    person.firstname = "Just";
    person.getFullName();
    

    This is very simple example, where the 'nestedness' of the objects is minimal. For your application it will be much higher, and individual static / value responsibilities of an complex object can be another complex object, such as your commands are already now (but a bit more memory saving and reuse oriented).

    ...this was a lot beating around the bush for 2 cents... next post goes to sensor work.

About

Avatar for allObjects @allObjects started