Subversion Repositories HomeAutomation

Rev

Rev 1191 | Rev 1195 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1.  
  2. loadScript("Logic/MenuItem.js");
  3.  
  4. function Display(type, name, id)
  5. {
  6.     /* We must always call the parent constructor, initialization
  7.        of variables could be done here, but initialize is a better place */
  8.     this.Service(type, name, id);
  9. }
  10.  
  11. /* We inherit from Service with this call, it must always be next
  12.    after the constructor */
  13. extend(Display, Service);
  14.  
  15. /* Declaration of instance variables, for static variables remove prototype */
  16.  
  17. /* format: dat objects, just use the time */
  18. Display.prototype.bookFromTime = null;
  19. Display.prototype.bookToTime = null;
  20.  
  21. /* the shortname for this exchangeobject */
  22. Display.prototype.shortName = null;
  23.  
  24. /* the name for this display (shown on first screen) */
  25. Display.prototype.niceName = null;
  26.  
  27. /* The display should regulary update and store the calendar */
  28. Display.prototype.exchangeData = null;
  29.  
  30. Display.prototype.myLCDService = null;
  31. Display.prototype.myRotaryService = null;
  32. Display.prototype.mySoftPwmService = null;
  33. Display.prototype.myInterval = null;
  34.  
  35. /*  */
  36. Display.prototype.exchangeCalendar = null;
  37. /*  */
  38. Display.prototype.exchangeCalendarFirstMenuItem = null;
  39. Display.prototype.exchangeCalendarLastMenuItem = null;
  40. Display.prototype.statusMenuItem = null;
  41. Display.prototype.bookMenuItem = null;
  42.  
  43. /* The currently displayed menuitem */
  44. Display.prototype.currentMenuItem = null;
  45.  
  46.  
  47. /* This function must always be declared, this is where all the startup code
  48.    should be placed. Gets called with arguments like what ids to use etc. */
  49. Display.prototype.initialize = function(initialArguments)
  50. {
  51.     /* We must always call the parent initialize */
  52.     this.Service.prototype.initialize.call(this, initialArguments);
  53.  
  54.     /* This is used for function declarations like the callbacks below */
  55.     var self = this;
  56.  
  57.     if (!this.myInitialArguments["HD44789"])
  58.     {
  59.         log(this.myName + ":" + this.myId + "> Failed to initialize, HD44789-config missing from config.\n");
  60.         return;
  61.     }
  62.    
  63.     if (!this.myInitialArguments["Rotary"])
  64.     {
  65.         log(this.myName + ":" + this.myId + "> Failed to initialize, Rotary-config missing from config.\n");
  66.         return;
  67.     }
  68.    
  69.     if (!this.myInitialArguments["softPWM"])
  70.     {
  71.         log(this.myName + ":" + this.myId + "> Failed to initialize, softPWM-config missing from config.\n");
  72.         return;
  73.     }
  74.    
  75.     if (!this.myInitialArguments["Name"])
  76.     {
  77.         log(this.myName + ":" + this.myId + "> Failed to initialize, Name-config missing from config.\n");
  78.         return;
  79.     }
  80.     this.niceName = this.myInitialArguments["Name"];
  81.  
  82.     if (!this.myInitialArguments["ShortName"])
  83.     {
  84.         log(this.myName + ":" + this.myId + "> Failed to initialize, Name-config missing from config.\n");
  85.         return;
  86.     }
  87.     this.shortName = this.myInitialArguments["ShortName"];
  88.    
  89.     /* Get the LCD service that we want from the ServiceManager, it takes type, service name, service id */
  90.     this.myLCDService = ServiceManager.getService("Can", "HD44789", this.myInitialArguments["HD44789"]["Id"]);
  91.     /* Add a callback for when the service goes online */
  92.     this.myLCDService.registerEventCallback("online", function(args) { self.lcdOnline(); });
  93.     /* If the service is already online we should call the handler here */
  94.     this.lcdOnline();
  95.     /* Add a callback for when the service goes offline */
  96.     this.myLCDService.registerEventCallback("offline", function(args) { self.lcdOffline(); });
  97.    
  98.     /* Get the Rotary service that we want from the ServiceManager, it takes type, service name, service id */
  99.     this.myRotaryService = ServiceManager.getService("Can", "Rotary", this.myInitialArguments["Rotary"]["Id"]);
  100.     /* Add a callback for when the encoder reports a new position */
  101.     this.myRotaryService.registerEventCallback("newPosition", function(args) { self.rotaryPosUpdate(args); });
  102.     /* Add a callback for when the encoder reports a new button status */
  103.     this.myRotaryService.registerEventCallback("newBtnStatus", function(args) { self.rotaryBtnUpdate(args); });
  104.     /* Add a callback for when the service goes online */
  105.     this.myRotaryService.registerEventCallback("online", function(args) { self.rotaryOnline(); });
  106.     /* If the service is already online we should call the handler here */
  107.     this.rotaryOnline();
  108.    
  109.     /* Get the softPWM service that we want from the ServiceManager, it takes type, service name, service id */
  110.     this.mySoftPwmService = ServiceManager.getService("Can", "softPWM", this.myInitialArguments["softPWM"]["Id"]);
  111.     /* Add a callback for when the service goes online */
  112.     this.mySoftPwmService.registerEventCallback("online", function(args) { self.softPwmOnline(); });
  113.     /* If the service is already online we should call the handler here */
  114.     this.softPwmOnline();
  115.    
  116.     this.exchangeCalendar = new ExchangeCalendar(function(shortname, data) { self.exchangeCalendarLookupCallback(shortname, data); });
  117.    
  118.     /* create the first menu item */
  119.     this.statusMenuItem = new MenuItem(this);
  120.     this.statusMenuItem.displayData[0] = this.lcdCenterText(this.niceName);
  121.     this.statusMenuItem.doUpdate = this.updateStatusMenuItem;
  122.     this.currentMenuItem = this.statusMenuItem;
  123.    
  124.     /* create the menuitem where you can choose to enter the booking sub-menu */
  125.     this.bookMenuItem = new MenuItem(this);
  126.     this.bookMenuItem.displayData[0] = this.lcdCenterText("Book room";
  127.     this.bookMenuItem.displayData[1] = this.lcdCenterText("");
  128.     this.bookMenuItem.doUpdate = this.updateBookMenuItem;
  129.  
  130.     /* connect the items as a linked list */
  131.     this.statusMenuItem.setNextItem(this.bookMenuItem);
  132.     this.statusMenuItem.setPrevItem(this.bookMenuItem);
  133.     /* set the function that shall be executed when knob is turned */
  134.     this.statusMenuItem.doRight = this.changeToNext;
  135.     this.statusMenuItem.doLeft = this.changeToPrev;
  136.    
  137.     /* connect the items as a linked list */
  138.     this.bookMenuItem.setNextItem(this.statusMenuItem);
  139.     this.bookMenuItem.setPrevItem(this.statusMenuItem);
  140.     /* set the function that shall be executed when knob is turned */
  141.     this.bookMenuItem.doRight = this.changeToNext;
  142.     this.bookMenuItem.doLeft = this.changeToPrev;
  143.    
  144.     /* create the menuitem where you can choose the to-time */
  145.     var menuChooseTo = new MenuItem(this);
  146.     menuChooseTo.displayData[1] = this.lcdCenterText("Ok     Cancel");
  147.     menuChooseTo.doUpdate = this.chooseBookTimeTo;
  148.    
  149.     this.bookMenuItem.doPress = this.startBooking;
  150.     this.bookMenuItem.setDescItem(menuChooseTo);
  151.    
  152.     /* create the menuitem where you can choose to book the room with OK */
  153.     var menuChooseOk = new MenuItem(this);
  154.     menuChooseOk.displayData[1] = this.lcdCenterText("<Ok>    Cancel");
  155.     menuChooseOk.doUpdate = this.setBookTime;
  156.  
  157.     /* create the menuitem where you can choose to cancel the booking */
  158.     var menuChooseCancel = new MenuItem(this);
  159.     menuChooseCancel.displayData[1] = this.lcdCenterText("Ok    <Cancel>");
  160.     menuChooseCancel.doUpdate = this.setBookTime;
  161.  
  162.     /* create the menuitem where you can choose the from-time */
  163.     var menuChooseFrom = new MenuItem(this);
  164.     menuChooseFrom.displayData[1] = this.lcdCenterText("Ok     Cancel");
  165.     menuChooseFrom.doUpdate = this.chooseBookTimeFrom;
  166.  
  167.     /* connect the items as a linked list */
  168.     menuChooseTo.setNextItem(menuChooseOk);
  169.     menuChooseTo.setPrevItem(menuChooseFrom);
  170.     /* set the function that shall be executed when knob is turned */
  171.     menuChooseTo.doRight = this.changeToNext;
  172.     menuChooseTo.doLeft = this.changeToPrev;
  173.     menuChooseTo.doPress = this.changeToDesc;
  174.  
  175.     /* connect the items as a linked list */
  176.     menuChooseOk.setNextItem(menuChooseCancel);
  177.     menuChooseOk.setPrevItem(menuChooseTo);
  178.     /* set the function that shall be executed when knob is turned */
  179.     menuChooseOk.doRight = this.changeToNext;
  180.     menuChooseOk.doLeft = this.changeToPrev;
  181.  
  182.     /* connect the items as a linked list */
  183.     menuChooseCancel.setNextItem(menuChooseFrom);
  184.     menuChooseCancel.setPrevItem(menuChooseOk);
  185.     menuChooseCancel.setDescItem(this.bookMenuItem);
  186.     /* set the function that shall be executed when knob is turned */
  187.     menuChooseCancel.doRight = this.changeToNext;
  188.     menuChooseCancel.doLeft = this.changeToPrev;
  189.     menuChooseCancel.doPress = this.changeToDesc;
  190.  
  191.     /* connect the items as a linked list */
  192.     menuChooseFrom.setNextItem(menuChooseTo);
  193.     menuChooseFrom.setPrevItem(menuChooseCancel);
  194.     /* set the function that shall be executed when knob is turned */
  195.     menuChooseFrom.doRight = this.changeToNext;
  196.     menuChooseFrom.doLeft = this.changeToPrev;
  197.     menuChooseFrom.doPress = this.changeToDesc;
  198.  
  199.     /* create the menuitem where you can modify the to-time */
  200.     var menuSetTo = new MenuItem(this);
  201.     menuSetTo.doUpdate = this.setBookTimeTo;
  202.     menuSetTo.displayData[0] = this.lcdCenterText("Set end time");
  203.     menuSetTo.doRight = this.incBookTimeTo;
  204.     menuSetTo.doLeft = this.decBookTimeTo;
  205.     menuSetTo.doPress = this.changeToDesc;
  206.     menuSetTo.setDescItem(menuChooseTo);
  207.     menuChooseTo.setDescItem(menuSetTo);
  208.  
  209.     /* create the menuitem where you can modify the from-time */
  210.     var menuSetFrom = new MenuItem(this);
  211.     menuSetFrom.doUpdate = this.setBookTimeFrom;
  212.     menuSetFrom.displayData[0] = this.lcdCenterText("Set start time");
  213.     menuSetFrom.doRight = this.incBookTimeFrom;
  214.     menuSetFrom.doLeft = this.decBookTimeFrom;
  215.     menuSetFrom.doPress = this.changeToDesc;
  216.     menuSetFrom.setDescItem(menuChooseFrom);
  217.     menuChooseFrom.setDescItem(menuSetFrom);
  218.  
  219. }
  220.  
  221. Display.prototype.startBooking = function()
  222. {
  223.     this.parentDisplay.bookFromTime = new Date();
  224.     this.parentDisplay.bookToTime = new Date();
  225.     //this.bookFromTime.setHours(8);
  226.     //this.bookToTime.setHours(8);
  227.     if (this.parentDisplay.bookFromTime.getMinutes() < 30)
  228.     {
  229.         this.parentDisplay.bookFromTime.setMinutes(0);
  230.         this.parentDisplay.bookToTime.setMinutes(30);
  231.     }
  232.     else
  233.     {
  234.         this.parentDisplay.bookFromTime.setMinutes(30);
  235.         this.parentDisplay.bookToTime.setHours(this.parentDisplay.bookToTime.getHours()+1);
  236.         this.parentDisplay.bookToTime.setMinutes(0);
  237.     }
  238.  
  239.     this.parentDisplay.currentMenuItem = this.parentDisplay.currentMenuItem.descItem;
  240. }
  241.  
  242. Display.prototype.changeToDesc = function()
  243. {
  244.     if (this.descItem)
  245.     {
  246.         this.parentDisplay.currentMenuItem = this.descItem;
  247.     }
  248. }
  249.  
  250. Display.prototype.changeToNext = function()
  251. {
  252.     if (this.nextItem)
  253.     {
  254.         this.parentDisplay.currentMenuItem = this.nextItem;
  255.     }
  256. }
  257.  
  258. Display.prototype.changeToPrev = function()
  259. {
  260.     if (this.prevItem)
  261.     {
  262.         this.parentDisplay.currentMenuItem = this.prevItem;
  263.     }
  264. }
  265.  
  266. Display.prototype.incBookTimeTo = function()
  267. {
  268.     //FIXME: constraints?
  269.     if (this.parentDisplay.bookFromTime.getHours() < 23)
  270.     {
  271.         this.parentDisplay.bookToTime.setMinutes(this.parentDisplay.bookToTime.getMinutes() + 30);
  272.     }
  273. }
  274.  
  275. Display.prototype.decBookTimeTo = function()
  276. {
  277.     //FIXME: constraints?
  278.     var now = new Date();
  279.     if (this.parentDisplay.bookToTime.getHours() >= now.getHours())
  280.     {
  281.         this.parentDisplay.bookToTime.setMinutes(this.parentDisplay.bookToTime.getMinutes() - 30);
  282.     }
  283. }
  284.  
  285. Display.prototype.incBookTimeFrom = function()
  286. {
  287.     //FIXME: constraints?
  288.     if (this.parentDisplay.bookFromTime.getHours() < 23)
  289.     {
  290.         this.parentDisplay.bookFromTime.setMinutes(this.parentDisplay.bookFromTime.getMinutes() + 30);
  291.     }
  292. }
  293.  
  294. Display.prototype.decBookTimeFrom = function()
  295. {
  296.     //FIXME: constraints?
  297.     var now = new Date();
  298.     if (this.parentDisplay.bookFromTime.getHours() >= now.getHours())
  299.     {
  300.         this.parentDisplay.bookFromTime.setMinutes(this.parentDisplay.bookFromTime.getMinutes() - 30);
  301.     }
  302. }
  303.  
  304. Display.prototype.setBookTimeFrom = function()
  305. {
  306.     this.displayData[1] = "      <"+this.parentDisplay.bookFromTime.getTimeShortFormated()+">       ";
  307. }
  308.  
  309. Display.prototype.setBookTimeTo = function()
  310. {
  311.     this.displayData[1] = "      <"+this.parentDisplay.bookToTime.getTimeShortFormated()+">       ";
  312. }
  313.  
  314. Display.prototype.chooseBookTimeTo = function()
  315. {
  316.     this.displayData[0] = "  "+this.parentDisplay.bookFromTime.getTimeShortFormated()+"  - <"
  317.                                 +this.parentDisplay.bookToTime.getTimeShortFormated()+">  ";
  318. }
  319.  
  320. Display.prototype.chooseBookTimeFrom = function()
  321. {
  322.     this.displayData[0] = " <"+this.parentDisplay.bookFromTime.getTimeShortFormated()+"> -  "
  323.                                 +this.parentDisplay.bookToTime.getTimeShortFormated()+"   ";
  324. }
  325.  
  326. Display.prototype.setBookTime = function()
  327. {
  328.     this.displayData[0] = "  "+this.parentDisplay.bookFromTime.getTimeShortFormated()+"  -  "
  329.                                 +this.parentDisplay.bookToTime.getTimeShortFormated()+"   ";
  330. }
  331.  
  332. Display.prototype.updateStatusMenuItem = function()
  333. {
  334.     var date = new Date();
  335.     var dateAndTime = "" + date.getTimeShortFormated();
  336.     this.displayData[1] = "       " + dateAndTime + "        ";
  337.    
  338.     if (this.parentDisplay.exchangeCalendarFirstMenuItem && this.parentDisplay.exchangeCalendarLastMenuItem)
  339.     {
  340.         this.parentDisplay.statusMenuItem.setNextItem(this.parentDisplay.exchangeCalendarFirstMenuItem);
  341.         this.parentDisplay.bookMenuItem.setPrevItem(this.parentDisplay.exchangeCalendarLastMenuItem);
  342.     }
  343. }
  344.  
  345. Display.prototype.updateBookMenuItem = function()
  346. {
  347.     if (this.parentDisplay.exchangeCalendarFirstMenuItem && this.parentDisplay.exchangeCalendarLastMenuItem)
  348.     {
  349.         this.parentDisplay.statusMenuItem.setNextItem(this.parentDisplay.exchangeCalendarFirstMenuItem);
  350.         this.parentDisplay.bookMenuItem.setPrevItem(this.parentDisplay.exchangeCalendarLastMenuItem);
  351.     }
  352. }
  353.  
  354. Display.prototype.exchangeCalendarLookupCallback = function(shortname, data)
  355. {
  356. log("callback: "+shortname+" \n");
  357.     if (shortname == this.shortName)
  358.     {
  359.         //FIXME check if data contains error tag and error message, print to log and keep previous data?
  360.         this.exchangeData = data;
  361.        
  362.         this.createCalendarMenu();
  363.     }
  364. }
  365.  
  366. /* this function parses calendar data from exchange-script and creates a menu */
  367. Display.prototype.createCalendarMenu = function()
  368. {
  369. log("createCalendar \n");
  370.     if (this.exchangeData)
  371.     {
  372. log("have data \n");
  373.         var lastMenuItem;
  374.         for (var i = 0; i < this.exchangeData.meetings.length; i++)
  375.         {
  376. log("looping \n");
  377.             /* create the menuitem for a calendar meeting */
  378.             var menu = new MenuItem(this);
  379.             menu.displayData[0] = this.lcdCenterText(this.exchangeData.meetings[i].organizer);
  380.             menu.displayData[1] = this.lcdCenterText(this.exchangeData.meetings[i].start.replace(":",".") + " - "
  381.                                         + this.exchangeData.meetings[i].end.replace(":","."));
  382.             menu.doRight = this.changeToNext;
  383.             menu.doLeft = this.changeToPrev;
  384.            
  385.             if (i == 0)
  386.             {
  387.                 this.exchangeCalendarFirstMenuItem = menu;
  388.             }
  389.             else
  390.             {
  391.                 menu.setPrevItem(lastMenuItem);
  392.                 lastMenuItem.setNextItem(menu);
  393.             }
  394.            
  395.             lastMenuItem = menu;
  396.         }
  397.         this.exchangeCalendarLastMenuItem = lastMenuItem;
  398.         this.exchangeCalendarLastMenuItem.setNextItem(this.bookMenuItem);
  399.         this.exchangeCalendarFirstMenuItem.setPrevItem(this.statusMenuItem);
  400.     }
  401. }
  402.  
  403. Display.prototype.softPwmOnline = function()
  404. {
  405. }
  406.  
  407. Display.prototype.rotaryOnline = function()
  408. {
  409. }
  410.  
  411. Display.prototype.rotaryPosUpdate = function(SwitchId)
  412. {
  413.     for (var i = 0; i < this.myRotaryService.getSteps(SwitchId); i++)
  414.     {
  415.         if (this.myRotaryService.getDirection(SwitchId) == "Clockwise")
  416.         {
  417.             if (this.currentMenuItem.doRight)
  418.             {
  419.                 this.currentMenuItem.doRight();
  420.             }
  421.         }
  422.         else
  423.         {
  424.             if (this.currentMenuItem.doLeft)
  425.             {
  426.                 this.currentMenuItem.doLeft();
  427.             }
  428.         }
  429.     }
  430.    
  431.     this.updateDisplay();
  432. }
  433.  
  434. Display.prototype.rotaryBtnUpdate = function(SwitchId)
  435. {
  436.     if (this.myRotaryService.getButtonStatus(SwitchId) == "Released")
  437.     {
  438.         if (this.currentMenuItem.doPress)
  439.         {
  440.             this.currentMenuItem.doPress();
  441.         }
  442.     }
  443.     this.updateDisplay();
  444. }
  445.  
  446. Display.prototype.updateDisplay = function()
  447. {
  448.     /* see if the current menuitem wants to update itself */
  449.     if (this.currentMenuItem.doUpdate)
  450.     {
  451.         this.currentMenuItem.doUpdate();
  452.     }
  453.  
  454.     /* Clear the LCD screen */
  455.     //this.myLCDService.clearScreen();
  456.    
  457.     /* send the data for the current menuitem to display */
  458.     for (var i = 0; i < this.currentMenuItem.displayData.length; i++)
  459.     {
  460.         this.myLCDService.printText(0, i, this.currentMenuItem.displayData[i]);
  461.     }
  462.    
  463. }
  464.  
  465. Display.prototype.lcdCenterText = function(text)
  466. {
  467.     returnText = text;
  468.     var displayWidth = this.myLCDService.getWidth();
  469.     /* pad on both sides with spaces to displayWidth */
  470.     returnText = text.pad(displayWidth, " ", 2);
  471.    
  472.     /*if (displayWidth > text.length)
  473.     {
  474.         paddingLen = displayWidth - text.length;
  475.         paddingLen = Math.round((paddingLen/2-0.5));
  476.         returnText = text
  477.     }*/
  478.    
  479.     return returnText;
  480. }
  481.  
  482. Display.prototype.lcdOffline = function()
  483. {
  484.     /* If we have no interval timer running do nothing */
  485.     if (this.myInterval != null)
  486.     {
  487.         /* Stop the interval */
  488.         this.myInterval.stop();
  489.     }
  490. }
  491.  
  492. Display.prototype.lcdOnline = function()
  493. {
  494.     /* If service is not online do nothing */
  495.     if (this.myLCDService.isOnline())
  496.     {
  497.         /* Clear the LCD screen */
  498.         this.myLCDService.clearScreen();
  499.         /* Set backlight to max */
  500.         this.myLCDService.setBacklight(255);
  501.  
  502.         /* If we have no interval timer running start it */
  503.         if (this.myInterval == null)
  504.         {
  505.             var self = this;
  506.        
  507.             /* Start interval timer for our printout. Arguments are the callback function and time in milliseconds */
  508.             this.myInterval = new Interval(function() { self.timerUpdate() }, 60000);
  509.         }
  510.        
  511.         this.myInterval.start();
  512.        
  513.         this.timerUpdate();
  514.     }
  515. }
  516.  
  517. Display.prototype.timerUpdate = function()
  518. {
  519.     /* If LCD service is not online do nothing */
  520.     if (this.myLCDService.isOnline())
  521.     {
  522.         this.exchangeCalendar.lookup(this.shortName);
  523.        
  524.         /* update the info on display */
  525.         this.updateDisplay();
  526.     }
  527. }
  528.  
  529.