Subversion Repositories HomeAutomation

Rev

Rev 1190 | 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.     this.parentDisplay.bookToTime.setMinutes(this.parentDisplay.bookToTime.getMinutes() + 30);
  270. }
  271.  
  272. Display.prototype.decBookTimeTo = function()
  273. {
  274.     //FIXME: constraints?
  275.     this.parentDisplay.bookToTime.setMinutes(this.parentDisplay.bookToTime.getMinutes() - 30);
  276. }
  277.  
  278. Display.prototype.incBookTimeFrom = function()
  279. {
  280.     //FIXME: constraints?
  281.     this.parentDisplay.bookFromTime.setMinutes(this.parentDisplay.bookFromTime.getMinutes() + 30);
  282. }
  283.  
  284. Display.prototype.decBookTimeFrom = function()
  285. {
  286.     //FIXME: constraints?
  287.         this.parentDisplay.bookFromTime.setMinutes(this.parentDisplay.bookFromTime.getMinutes() - 30);
  288. }
  289.  
  290. Display.prototype.setBookTimeFrom = function()
  291. {
  292.     this.displayData[1] = "      <"+this.parentDisplay.bookFromTime.getTimeShortFormated()+">       ";
  293. }
  294.  
  295. Display.prototype.setBookTimeTo = function()
  296. {
  297.     this.displayData[1] = "      <"+this.parentDisplay.bookToTime.getTimeShortFormated()+">       ";
  298. }
  299.  
  300. Display.prototype.chooseBookTimeTo = function()
  301. {
  302.     this.displayData[0] = "  "+this.parentDisplay.bookFromTime.getTimeShortFormated()+"  - <"
  303.                                 +this.parentDisplay.bookToTime.getTimeShortFormated()+">  ";
  304. }
  305.  
  306. Display.prototype.chooseBookTimeFrom = function()
  307. {
  308.     this.displayData[0] = " <"+this.parentDisplay.bookFromTime.getTimeShortFormated()+"> -  "
  309.                                 +this.parentDisplay.bookToTime.getTimeShortFormated()+"   ";
  310. }
  311.  
  312. Display.prototype.setBookTime = function()
  313. {
  314.     this.displayData[0] = "  "+this.parentDisplay.bookFromTime.getTimeShortFormated()+"  -  "
  315.                                 +this.parentDisplay.bookToTime.getTimeShortFormated()+"   ";
  316. }
  317.  
  318. Display.prototype.updateStatusMenuItem = function()
  319. {
  320.     var date = new Date();
  321.     var dateAndTime = "" + date.getTimeShortFormated();
  322.     this.displayData[1] = "       " + dateAndTime + "        ";
  323.    
  324.     if (this.parentDisplay.exchangeCalendarFirstMenuItem && this.parentDisplay.exchangeCalendarLastMenuItem)
  325.     {
  326.         this.parentDisplay.statusMenuItem.setNextItem(this.parentDisplay.exchangeCalendarFirstMenuItem);
  327.         this.parentDisplay.bookMenuItem.setPrevItem(this.parentDisplay.exchangeCalendarLastMenuItem);
  328.     }
  329. }
  330.  
  331. Display.prototype.updateBookMenuItem = function()
  332. {
  333.     if (this.parentDisplay.exchangeCalendarFirstMenuItem && this.parentDisplay.exchangeCalendarLastMenuItem)
  334.     {
  335.         this.parentDisplay.statusMenuItem.setNextItem(this.parentDisplay.exchangeCalendarFirstMenuItem);
  336.         this.parentDisplay.bookMenuItem.setPrevItem(this.parentDisplay.exchangeCalendarLastMenuItem);
  337.     }
  338. }
  339.  
  340. Display.prototype.exchangeCalendarLookupCallback = function(shortname, data)
  341. {
  342. log("callback: "+shortname+" \n");
  343.     if (shortname == this.shortName)
  344.     {
  345.         //FIXME check if data contains error tag and error message, print to log and keep previous data?
  346.         this.exchangeData = data;
  347.        
  348.         this.createCalendarMenu();
  349.     }
  350. }
  351.  
  352. /* this function parses calendar data from exchange-script and creates a menu */
  353. Display.prototype.createCalendarMenu = function()
  354. {
  355. log("createCalendar \n");
  356.     if (this.exchangeData)
  357.     {
  358. log("have data \n");
  359.         var lastMenuItem;
  360.         for (var i = 0; i < this.exchangeData.meetings.length; i++)
  361.         {
  362. log("looping \n");
  363.             /* create the menuitem for a calendar meeting */
  364.             var menu = new MenuItem(this);
  365.             menu.displayData[0] = this.lcdCenterText(this.exchangeData.meetings[i].organizer);
  366.             menu.displayData[1] = this.lcdCenterText(this.exchangeData.meetings[i].start.replace(":",".") + " - "
  367.                                         + this.exchangeData.meetings[i].end.replace(":","."));
  368.             menu.doRight = this.changeToNext;
  369.             menu.doLeft = this.changeToPrev;
  370.            
  371.             if (i == 0)
  372.             {
  373.                 this.exchangeCalendarFirstMenuItem = menu;
  374.             }
  375.             else
  376.             {
  377.                 menu.setPrevItem(lastMenuItem);
  378.                 lastMenuItem.setNextItem(menu);
  379.             }
  380.            
  381.             lastMenuItem = menu;
  382.         }
  383.         this.exchangeCalendarLastMenuItem = lastMenuItem;
  384.         this.exchangeCalendarLastMenuItem.setNextItem(this.bookMenuItem);
  385.         this.exchangeCalendarFirstMenuItem.setPrevItem(this.statusMenuItem);
  386.     }
  387. }
  388.  
  389. Display.prototype.softPwmOnline = function()
  390. {
  391. }
  392.  
  393. Display.prototype.rotaryOnline = function()
  394. {
  395. }
  396.  
  397. Display.prototype.rotaryPosUpdate = function(SwitchId)
  398. {
  399.     for (var i = 0; i < this.myRotaryService.getSteps(SwitchId); i++)
  400.     {
  401.         if (this.myRotaryService.getDirection(SwitchId) == "Clockwise")
  402.         {
  403.             if (this.currentMenuItem.doRight)
  404.             {
  405.                 this.currentMenuItem.doRight();
  406.             }
  407.         }
  408.         else
  409.         {
  410.             if (this.currentMenuItem.doLeft)
  411.             {
  412.                 this.currentMenuItem.doLeft();
  413.             }
  414.         }
  415.     }
  416.    
  417.     this.updateDisplay();
  418. }
  419.  
  420. Display.prototype.rotaryBtnUpdate = function(SwitchId)
  421. {
  422.     if (this.myRotaryService.getButtonStatus(SwitchId) == "Released")
  423.     {
  424.         if (this.currentMenuItem.doPress)
  425.         {
  426.             this.currentMenuItem.doPress();
  427.         }
  428.     }
  429.     this.updateDisplay();
  430. }
  431.  
  432. Display.prototype.updateDisplay = function()
  433. {
  434.     /* see if the current menuitem wants to update itself */
  435.     if (this.currentMenuItem.doUpdate)
  436.     {
  437.         this.currentMenuItem.doUpdate();
  438.     }
  439.  
  440.     /* Clear the LCD screen */
  441.     //this.myLCDService.clearScreen();
  442.    
  443.     /* send the data for the current menuitem to display */
  444.     for (var i = 0; i < this.currentMenuItem.displayData.length; i++)
  445.     {
  446.         this.myLCDService.printText(0, i, this.currentMenuItem.displayData[i]);
  447.     }
  448.    
  449. }
  450.  
  451. Display.prototype.lcdCenterText = function(text)
  452. {
  453.     returnText = text;
  454.     var displayWidth = this.myLCDService.getWidth();
  455.     /* pad on both sides with spaces to displayWidth */
  456.     returnText = text.pad(displayWidth, " ", 2);
  457.    
  458.     /*if (displayWidth > text.length)
  459.     {
  460.         paddingLen = displayWidth - text.length;
  461.         paddingLen = Math.round((paddingLen/2-0.5));
  462.         returnText = text
  463.     }*/
  464.    
  465.     return returnText;
  466. }
  467.  
  468. Display.prototype.lcdOffline = function()
  469. {
  470.     /* If we have no interval timer running do nothing */
  471.     if (this.myInterval != null)
  472.     {
  473.         /* Stop the interval */
  474.         this.myInterval.stop();
  475.     }
  476. }
  477.  
  478. Display.prototype.lcdOnline = function()
  479. {
  480.     /* If service is not online do nothing */
  481.     if (this.myLCDService.isOnline())
  482.     {
  483.         /* Clear the LCD screen */
  484.         this.myLCDService.clearScreen();
  485.         /* Set backlight to max */
  486.         this.myLCDService.setBacklight(255);
  487.  
  488.         /* If we have no interval timer running start it */
  489.         if (this.myInterval == null)
  490.         {
  491.             var self = this;
  492.        
  493.             /* Start interval timer for our printout. Arguments are the callback function and time in milliseconds */
  494.             this.myInterval = new Interval(function() { self.timerUpdate() }, 60000);
  495.         }
  496.        
  497.         this.myInterval.start();
  498.        
  499.         this.timerUpdate();
  500.     }
  501. }
  502.  
  503. Display.prototype.timerUpdate = function()
  504. {
  505.     /* If LCD service is not online do nothing */
  506.     if (this.myLCDService.isOnline())
  507.     {
  508.         this.exchangeCalendar.lookup(this.shortName);
  509.        
  510.         /* update the info on display */
  511.         this.updateDisplay();
  512.     }
  513. }
  514.  
  515.