Subversion Repositories HomeAutomation

Rev

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