Subversion Repositories HomeAutomation

Rev

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

  1.  
  2. function CanNode(hardwareId, numberOfModules)
  3. {
  4.     this.myHardwareId = hardwareId;
  5.     this.myNumberOfModules = numberOfModules;
  6.     this.myModules = new Array();
  7.     this.myHeartbeatTime = 0;
  8.     this.myIsOnline = false;
  9.     this.stopProgramming();
  10. }
  11.  
  12. CanNode.prototype.myIsOnline = null;
  13. CanNode.prototype.myHardwareId = null;
  14. CanNode.prototype.myNumberOfModules = null;
  15. CanNode.prototype.myModules = null;
  16. CanNode.prototype.myHeartbeatTime = null;
  17. CanNode.prototype.myProgrammingIsBios = null;
  18. CanNode.prototype.myProgramming = null;
  19. CanNode.prototype.myProgrammingHex = null;
  20. CanNode.prototype.myProgrammingHexAddress = null;
  21. CanNode.prototype.myProgrammingOffset = null;
  22. CanNode.prototype.myProgrammingCallback = null;
  23. CanNode.prototype.myProgrammingWantAck = null;
  24. CanNode.prototype.myProgrammingState = null;
  25. CanNode.prototype.myProgrammingLastPercent = null;
  26. CanNode.prototype.myProgrammingLastTenPercent = null;
  27. CanNode.prototype.myProgrammingnrOfTicks = null;
  28. CanNode.prototype.myProgrammingTimeout = null;
  29. CanNode.prototype.myProgrammingResend = null;
  30. CanNode.prototype.myProgrammingLastPacket = null;
  31. CanNode.prototype.myProgrammingTimeStarted = null;
  32. CanNode.prototype.myResetCallback = null;
  33. CanNode.prototype.myResetTimer = null;
  34.  
  35. CanNode.prototype.isOnline = function()
  36. {
  37.     return this.myIsOnline;
  38. }
  39.  
  40. CanNode.prototype.start = function()
  41. {
  42.     var canMessage = new CanNMTMessage("nmt", "Start_App");
  43.     canMessage.setData("HardwareId", this.myHardwareId);
  44.     canMessage.send();
  45. }
  46.  
  47. CanNode.prototype.reset = function(callback)
  48. {
  49.     var self = this;
  50.    
  51.     if (callback)
  52.     {
  53.         this.myResetCallback = callback;
  54.         if (this.myResetTimer)
  55.         {
  56.             this.myResetTimer.stop();
  57.         }
  58.        
  59.         this.myResetTimer = new Interval(   function()
  60.                             {
  61.                                 self.myResetTimer.stop();
  62.                                 self.myResetTimer = null;
  63.                                 self.myResetCallback(false);
  64.                                 self.myResetCallback = null;
  65.                             }, 5000);
  66.         this.myResetTimer.start();
  67.     }
  68.  
  69.     var canMessage = new CanNMTMessage("nmt", "Reset");
  70.     canMessage.setData("HardwareId", this.myHardwareId);
  71.     canMessage.send();
  72.    
  73.     this.setOffline();
  74. }
  75.  
  76. CanNode.prototype.startApplication = function()
  77. {
  78.     var canMessage = new CanNMTMessage("nmt", "Start_App");
  79.     canMessage.setData("HardwareId", this.myHardwareId);
  80.     canMessage.send();
  81. }
  82.  
  83. CanNode.prototype.handleHeartbeat = function(numberOfModules)
  84. {
  85.     if (numberOfModules)
  86.     {
  87.         this.myNumberOfModules = numberOfModules;
  88.     }
  89.    
  90.     if (this.myNumberOfModules == null || this.myNumberOfModules > this.myModules.length)
  91.     {
  92.         var canMessage = new CanMessage("mnmt", "To_Owner", "", 0, "List");
  93.         canMessage.setData("HardwareId", this.myHardwareId);
  94.         canMessage.send();
  95.     }
  96.    
  97.     this.onlineHandler();
  98. }
  99.  
  100. CanNode.prototype.startProgramming = function(hexData, progressCallback, isBios)
  101. {
  102.     if (isBios)
  103.     {
  104.         this.myProgrammingIsBios = isBios;
  105.     }
  106.     else
  107.     {
  108.         this.myProgrammingIsBios = false;
  109.     }
  110.    
  111.     this.myProgramming = true;
  112.     this.myProgrammingHex = hexData;
  113.     this.myProgrammingCallback = progressCallback;
  114.    
  115.     CanProgrammingNode = this;
  116.    
  117.     var self = this;
  118.     this.myProgrammingTimeout = new Interval(function() { self.programmingTimeout() }, 6000);
  119.     this.myProgrammingTimeout.start();
  120.     this.myProgrammingState = "RESET";
  121.  
  122.     this.reset();
  123. }
  124.  
  125. CanNode.prototype.programmingTimeout = function()
  126. {
  127.     switch (this.myProgrammingState)
  128.     {
  129.     case "RESET":
  130.         this.stopProgramming(true, "Timeout while waiting for node to reset");
  131.         this.reset();
  132.         break;
  133.     case "DATA":
  134.         this.stopProgramming(true, "Timeout while waiting for node to ack data packet");
  135.         this.reset();
  136.         break;
  137.     case "END":
  138.         this.stopProgramming(true, "Timeout while waiting for node to ack data packet*");
  139.         this.reset();
  140.         break;
  141.     case "CRC":
  142.         this.stopProgramming(true, "Timeout while waiting for node to send crc");
  143.         this.reset();
  144.         break;
  145.     case "COPY":
  146.         //this will never occur, bios does not send ack for copy command, it just moves data in flash then reset itself
  147.         break;
  148.     default:
  149.         break;
  150.     }
  151. }
  152.  
  153. CanNode.prototype.programmingResend = function()
  154. {
  155.     this.myProgrammingResend.setTimeout(200);
  156.     //if we did not got ack then try to resend the data
  157.     this.myProgrammingLastPacket.send();
  158. }
  159.  
  160. CanNode.prototype.handleBiosStart = function(biosVersion, hasApplication)
  161. {
  162.     if (this.myResetCallback)
  163.     {
  164.         this.myResetCallback(true);
  165.         this.myResetCallback = null;
  166.     }
  167.    
  168.     if (this.myResetTimer)
  169.     {
  170.         this.myResetTimer.stop();
  171.         this.myResetTimer = null;
  172.     }
  173.  
  174. //print("node was reset and bios just started, ver:" + biosVersion);
  175.     if (this.myProgramming)
  176.     {
  177.         this.myProgrammingHexAddress = this.myProgrammingHex.getAddrLower();
  178.         this.myProgrammingWantAck = ((this.myProgrammingHexAddress<<8)|(this.myProgrammingHexAddress>>8))&0xffff;
  179.    
  180.         var canMessage = new CanNMTMessage("nmt", "Pgm_Start");
  181.         canMessage.setData("HardwareId", this.myHardwareId);
  182.         canMessage.setData("Address0", this.myProgrammingHexAddress&0xff);
  183.         canMessage.setData("Address1", (this.myProgrammingHexAddress>>8)&0xff);
  184.         canMessage.setData("Address3", (this.myProgrammingHexAddress>>16)&0xff);
  185.         canMessage.setData("Address4", (this.myProgrammingHexAddress>>24)&0xff);
  186.         canMessage.send();
  187.         this.myProgrammingState = "DATA";
  188.        
  189.         var self = this;
  190.         this.myProgrammingTimeout.setTimeout(1000);
  191.        
  192.         //this.myProgrammingResend = new Interval(function() { self.programmingResend() }, 1100);
  193.         //this.myProgrammingResend.start();
  194.  
  195.         var date = new Date();
  196.         this.myProgrammingTimeStarted = date.getTime();
  197.  
  198.         this.myProgrammingCallback(true, "START", "Started programming of node", false);
  199.         this.myProgrammingCallback(true, "", "  0% [", true);
  200.     }
  201. }
  202.  
  203. CanNode.prototype.handleNack = function(data)
  204. {
  205.     stopProgramming(true, "Failed, got NACK, sending reset");
  206.     this.reset();
  207.     if (false) 
  208.     {
  209.     }
  210. }
  211.  
  212. CanNode.prototype.handleAck = function(data)
  213. {
  214.     this.myProgrammingTimeout.reset();
  215.  
  216.     if (data == this.myProgrammingWantAck) 
  217.     {
  218.         switch (this.myProgrammingState)
  219.         {
  220.         case "DATA":
  221.             var offset = this.myProgrammingHexOffset;
  222.             //this.myProgrammingResend.setTimeout(100);
  223.        
  224.             this.myProgrammingWantAck = ((offset<<8)|(offset>>8))&0xffff;
  225.             //var bytesLeft = this.myProgrammingHex.getAddrUpper() - (this.myProgrammingHexAddress+this.myProgrammingHexOffset);
  226.             var bytesLeft = this.myProgrammingHex.getLength() - this.myProgrammingHexOffset;
  227.            
  228.             //here we must handle the possibility that data is less then 48 bits
  229.             var canMessage = new CanNMTMessage("nmt", "Pgm_Data_48");
  230.             switch (bytesLeft)
  231.             {
  232.             case 1:
  233.                 canMessage = new CanNMTMessage("nmt", "Pgm_Data_8");
  234.                 break;
  235.             case 2:
  236.                 canMessage = new CanNMTMessage("nmt", "Pgm_Data_16");
  237.                 break;
  238.             case 3:
  239.                 canMessage = new CanNMTMessage("nmt", "Pgm_Data_24");
  240.                 break;
  241.             case 4:
  242.                 canMessage = new CanNMTMessage("nmt", "Pgm_Data_32");
  243.                 break;
  244.             case 5:
  245.                 canMessage = new CanNMTMessage("nmt", "Pgm_Data_40");
  246.                 break;
  247.             }
  248.            
  249.             canMessage.setData("Offset0", offset&0xff);
  250.             canMessage.setData("Offset1", (offset>>8)&0xff);
  251.             for (var i=0; i<bytesLeft && i<6; i++)
  252.             {
  253.                 switch (i)
  254.                 {
  255.                 case 0:
  256.                     canMessage.setData("Data0", this.myProgrammingHex.getByte(offset));
  257.                     break;
  258.                 case 1:
  259.                     canMessage.setData("Data1", this.myProgrammingHex.getByte(offset));
  260.                     break;
  261.                 case 2:
  262.                     canMessage.setData("Data2", this.myProgrammingHex.getByte(offset));
  263.                     break;
  264.                 case 3:
  265.                     canMessage.setData("Data3", this.myProgrammingHex.getByte(offset));
  266.                     break;
  267.                 case 4:
  268.                     canMessage.setData("Data4", this.myProgrammingHex.getByte(offset));
  269.                     break;
  270.                 case 5:
  271.                     canMessage.setData("Data5", this.myProgrammingHex.getByte(offset));
  272.                     break;
  273.                 }
  274.                 offset++;
  275.             }
  276.             canMessage.send();
  277.             this.myProgrammingHexOffset = offset;
  278.  
  279.             if (this.myProgrammingHexOffset >= this.myProgrammingHex.getLength()) {
  280.                 this.myProgrammingState = "END";
  281.             }
  282.            
  283.             //this.myProgrammingCallback(true, "PROGRESS", this.myProgrammingHexOffset + ":" + this.myProgrammingHex.getLength(), false);
  284.             var percent = 100*this.myProgrammingHexOffset / this.myProgrammingHex.getLength();
  285.             if (percent >= this.myProgrammingLastPercent+2.5)
  286.             {
  287.                 this.myProgrammingCallback(true, "", "=", true);
  288.                 this.myProgrammingLastPercent+=2.5;
  289.                 this.myProgrammingnrOfTicks++;
  290.             }
  291.             if (percent > this.myProgrammingLastTenPercent+10)
  292.             {
  293.                 for (var i=this.myProgrammingnrOfTicks; i<40; i++) this.myProgrammingCallback(true, "", " ", true);
  294.                 this.myProgrammingCallback(true, "", "]", true);
  295.                 this.myProgrammingCallback(true, "", "\r", true);
  296.                 this.myProgrammingCallback(true, "", " "+Math.round(percent)+"% [", true);
  297.                 this.myProgrammingLastTenPercent+=10;
  298.                 for (var i=0; i<this.myProgrammingnrOfTicks; i++) this.myProgrammingCallback(true, "", "=", true);
  299.             }
  300.            
  301.             this.myProgrammingLastPacket = canMessage;
  302.             break;
  303.        
  304.         case "END":
  305.             this.myProgrammingWantAck = ((this.myProgrammingHex.getCRC16()<<8)|(this.myProgrammingHex.getCRC16()>>8))&0xffff;
  306.            
  307.             var timeElapsed = 0;
  308.             var printTime = "";
  309.             if (this.myProgrammingTimeStarted>0)
  310.             {
  311.                 var date = new Date();
  312.                 timeElapsed = date.getTime() - this.myProgrammingTimeStarted;
  313.                 printTime = " in " + Math.round(timeElapsed/1000) + "s, " + Math.round(this.myProgrammingHex.getLength()*1000/timeElapsed)+"bytes/s";
  314.             }
  315.            
  316.             var canMessage = new CanNMTMessage("nmt", "Pgm_End");
  317.             canMessage.send();
  318.  
  319.             this.myProgrammingState = "CRC";
  320.             for (var i=this.myProgrammingnrOfTicks; i<40; i++) this.myProgrammingCallback(true, "", " ", true);
  321.             this.myProgrammingCallback(true, "", "]", true);
  322.             this.myProgrammingCallback(true, "", "\r", true);
  323.             this.myProgrammingCallback(true, "", "100% [========================================]"+printTime, true);
  324.  
  325.             if (this.myProgrammingResend != null)
  326.             {
  327.                 /* Stop the interval */
  328.                 this.myProgrammingResend.stop();
  329.             }
  330.  
  331.             break;
  332.            
  333.         case "CRC":
  334.             //is this a bios programming?
  335.             if (false)
  336.             {
  337.                 this.myProgrammingState = "COPY";
  338.                 this.myProgrammingCallback(true, "PROGRESS", "Start to copy bios to new location", false);
  339.                 var canMessage = new CanNMTMessage("nmt", "Pgm_Copy");
  340.                 canMessage.setData("Source0", source);
  341.                 canMessage.setData("Source1", source);
  342.                 canMessage.setData("Destination0", destination);
  343.                 canMessage.setData("Destination1", destination);
  344.                 canMessage.setData("Length0", length);
  345.                 canMessage.setData("Length1", length);
  346.                 canMessage.send();
  347.                 this.stopProgramming();
  348.             }
  349.             else
  350.             {
  351.                 this.stopProgramming(true, "Done, successful");
  352.                 this.reset();
  353.             }
  354.             break;
  355.        
  356.         case "COPY":    //this will never occur, bios does not send ack for copy command, it just moves data in flash then reset itself
  357.             break;
  358.            
  359.         default:
  360.             break;
  361.         }
  362.     }
  363.     else
  364.     {
  365.         switch (this.myProgrammingState)
  366.         {
  367.         case "DATA":
  368.             //Fall through
  369.         case "END":
  370.             ///TODO: We got something that was not correct... we should abort
  371.             this.stopProgramming(true, "Failed to program, ack had wrong offset, expected data: "+this.myProgrammingWantAck+" got: "+data);
  372.             this.reset();
  373.             break;
  374.         case "CRC":
  375.             this.stopProgramming(true, "Failed to program, CRC not matching, expected data: "+this.myProgrammingWantAck+" got: "+data);
  376.             this.reset();
  377.             break;
  378.         case "COPY":    //this will never occur, bios does not send ack for copy command, it just moves data in flash then reset itself
  379.             break;
  380.         default:
  381.             break;
  382.         }
  383.     }
  384. }
  385.  
  386. CanNode.prototype.stopProgramming = function(status, text)
  387. {
  388.     if (status && text)
  389.     {
  390.         this.myProgrammingCallback(status, "\nSTOP", text, false);
  391.     }
  392.  
  393.     this.myProgrammingIsBios = false;
  394.     this.myProgramming = false;
  395.     this.myProgrammingHex = new Array();
  396.     this.myProgrammingHexAddress = 0;
  397.     this.myProgrammingHexOffset = 0;
  398.     this.myProgrammingCallback = function() {};
  399.     this.myProgrammingWantAck = null;
  400.     this.myProgrammingState = "";
  401.     this.myProgrammingLastPercent = 0;
  402.     this.myProgrammingLastTenPercent = 0;
  403.     this.myProgrammingnrOfTicks = 0;
  404.     this.myProgrammingTimeStarted = 0;
  405.  
  406.     if (this.myProgrammingTimeout != null)
  407.     {
  408.         /* Stop the interval */
  409.         this.myProgrammingTimeout.stop();
  410.     }
  411.     if (this.myProgrammingResend != null)
  412.     {
  413.         /* Stop the interval */
  414.         this.myProgrammingResend.stop();
  415.     }
  416.  
  417.     CanProgrammingNode = null;
  418. }
  419.  
  420.  
  421.  
  422. CanNode.prototype.addService = function(sequenceNumber, service)
  423. {
  424.     this.myModules[sequenceNumber] = service;
  425.     service.setOnline();
  426. }
  427.  
  428. CanNode.prototype.onlineHandler = function()
  429. {
  430.     var date = new Date();
  431.     this.myHeartbeatTime = date.getTimestamp();
  432.  
  433.     if (!this.myIsOnline)
  434.     {
  435.         this.myIsOnline = true;
  436.  
  437.         log(uint2hex(this.myHardwareId, 32) + "> Node went online\n");
  438.        
  439.         for (var n in this.myModules)
  440.         {
  441.             this.myModules[n].setOnline();
  442.         }
  443.     }
  444. }
  445.  
  446. CanNode.prototype.checkOffline = function()
  447. {
  448.     if (this.myIsOnline)
  449.     {
  450.         var date = new Date();
  451.         if (this.myHeartbeatTime + 10 < date.getTimestamp())
  452.         {
  453.             this.setOffline();
  454.         }
  455.     }
  456. }
  457.  
  458. CanNode.prototype.setOffline = function()
  459. {
  460.     if (this.myIsOnline)
  461.     {
  462.         this.myIsOnline = false;
  463.  
  464.         log(uint2hex(this.myHardwareId, 32) + "> Node went offline\n");
  465.        
  466.         for (var n in this.myModules)
  467.         {
  468.             this.myModules[n].setOffline();
  469.         }
  470.     }
  471. }
  472.