Subversion Repositories HomeAutomation

Rev

Rev 1195 | Rev 1204 | 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.bookToTime.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.     else
  353.     {
  354.         this.parentDisplay.statusMenuItem.setNextItem(this.parentDisplay.bookMenuItem);
  355.         this.parentDisplay.bookMenuItem.setPrevItem(this.parentDisplay.statusMenuItem);
  356.     }
  357. }
  358.  
  359. Display.prototype.exchangeCalendarLookupCallback = function(shortname, data)
  360. {
  361. //log("callback: "+shortname+" \n");
  362.     if (shortname == this.shortName)
  363.     {
  364.         //FIXME check if data contains error tag and error message, print to log and keep previous data?
  365.         if (data.error)
  366.         {
  367.             log("Display: got this error from exchange.php: " + data.error + "\n");
  368.         }
  369.         else
  370.         {
  371.             this.exchangeData = data;
  372.             this.createCalendarMenu();
  373.         }
  374.     }
  375. }
  376.  
  377. /* this function parses calendar data from exchange-script and creates a menu */
  378. Display.prototype.createCalendarMenu = function()
  379. {
  380.     this.exchangeCalendarLastMenuItem = null;
  381.     this.exchangeCalendarFirstMenuItem = null;
  382.    
  383. //log("createCalendar \n");
  384.     if (this.exchangeData)
  385.     {
  386. //log("have data \n");
  387.         var lastMenuItem;
  388.         for (var i = 0; i < this.exchangeData.meetings.length; i++)
  389.         {
  390. //log("looping \n");
  391.             /* create the menuitem for a calendar meeting */
  392.             var menu = new MenuItem(this);
  393.             menu.displayData[0] = this.lcdCenterText(this.exchangeData.meetings[i].subject);
  394.             menu.displayData[1] = this.lcdCenterText(this.exchangeData.meetings[i].start.replace(":",".") + " - "
  395.                                         + this.exchangeData.meetings[i].end.replace(":","."));
  396.             menu.doRight = this.changeToNext;
  397.             menu.doLeft = this.changeToPrev;
  398.            
  399.             if (i == 0)
  400.             {
  401.                 this.exchangeCalendarFirstMenuItem = menu;
  402.             }
  403.             else
  404.             {
  405.                 menu.setPrevItem(lastMenuItem);
  406.                 lastMenuItem.setNextItem(menu);
  407.             }
  408.            
  409.             lastMenuItem = menu;
  410.         }
  411.         this.exchangeCalendarLastMenuItem = lastMenuItem;
  412.         this.exchangeCalendarLastMenuItem.setNextItem(this.bookMenuItem);
  413.         this.exchangeCalendarFirstMenuItem.setPrevItem(this.statusMenuItem);
  414.     }
  415. }
  416.  
  417. Display.prototype.softPwmOnline = function()
  418. {
  419. }
  420.  
  421. Display.prototype.rotaryOnline = function()
  422. {
  423. }
  424.  
  425. Display.prototype.rotaryPosUpdate = function(SwitchId)
  426. {
  427.     for (var i = 0; i < this.myRotaryService.getSteps(SwitchId); i++)
  428.     {
  429.         if (this.myRotaryService.getDirection(SwitchId) == "Clockwise")
  430.         {
  431.             if (this.currentMenuItem.doRight)
  432.             {
  433.                 this.currentMenuItem.doRight();
  434.             }
  435.         }
  436.         else
  437.         {
  438.             if (this.currentMenuItem.doLeft)
  439.             {
  440.                 this.currentMenuItem.doLeft();
  441.             }
  442.         }
  443.     }
  444.    
  445.     this.updateDisplay();
  446. }
  447.  
  448. Display.prototype.rotaryBtnUpdate = function(SwitchId)
  449. {
  450.     if (this.myRotaryService.getButtonStatus(SwitchId) == "Released")
  451.     {
  452.         if (this.currentMenuItem.doPress)
  453.         {
  454.             this.currentMenuItem.doPress();
  455.         }
  456.     }
  457.     this.updateDisplay();
  458. }
  459.  
  460. Display.prototype.updateDisplay = function()
  461. {
  462.     /* see if the current menuitem wants to update itself */
  463.     if (this.currentMenuItem.doUpdate)
  464.     {
  465.         this.currentMenuItem.doUpdate();
  466.     }
  467.  
  468.     /* Clear the LCD screen */
  469.     //this.myLCDService.clearScreen();
  470.    
  471.     /* send the data for the current menuitem to display */
  472.     for (var i = 0; i < this.currentMenuItem.displayData.length; i++)
  473.     {
  474.         this.myLCDService.printText(0, i, this.currentMenuItem.displayData[i]);
  475.     }
  476.    
  477. }
  478.  
  479. Display.prototype.lcdCenterText = function(text)
  480. {
  481.     returnText = text;
  482.     var displayWidth = 20;  //this.myLCDService.getWidth();
  483.     /* pad on both sides with spaces to displayWidth */
  484.     returnText = text.pad(displayWidth, " ", 2);
  485.    
  486.     return returnText;
  487. }
  488.  
  489. Display.prototype.lcdOffline = function()
  490. {
  491.     /* If we have no interval timer running do nothing */
  492.     if (this.myInterval != null)
  493.     {
  494.         /* Stop the interval */
  495.         this.myInterval.stop();
  496.     }
  497. }
  498.  
  499. Display.prototype.lcdOnline = function()
  500. {
  501.     /* If service is not online do nothing */
  502.     if (this.myLCDService.isOnline())
  503.     {
  504.         /* Clear the LCD screen */
  505.         this.myLCDService.clearScreen();
  506.         /* Set backlight to max */
  507.         this.myLCDService.setBacklight(255);
  508.  
  509.         /* If we have no interval timer running start it */
  510.         if (this.myInterval == null)
  511.         {
  512.             var self = this;
  513.        
  514.             /* Start interval timer for our printout. Arguments are the callback function and time in milliseconds */
  515.             this.myInterval = new Interval(function() { self.timerUpdate() }, 60000);
  516.         }
  517.        
  518.         this.myInterval.start();
  519.        
  520.         this.timerUpdate();
  521.     }
  522. }
  523.  
  524. Display.prototype.setLED = function(red, green, blue)
  525. {
  526.    
  527. }
  528.  
  529. Display.prototype.timerUpdate = function()
  530. {
  531.     /* If LCD service is not online do nothing */
  532.     if (this.myLCDService.isOnline())
  533.     {
  534.         this.exchangeCalendar.lookup(this.shortName);
  535.        
  536.         /* update the info on display */
  537.         this.updateDisplay();
  538.     }
  539.    
  540.     /*if (this.mySoftPwmService.isOnline())
  541.     {
  542.         this.mySoftPwmService.setPWMValue(0, 0);
  543.         this.mySoftPwmService.setPWMValue(11, 1);
  544.         this.mySoftPwmService.setPWMValue(11, 2);
  545.     }*/
  546. }
  547.  
  548.