Subversion Repositories HomeAutomation

Rev

Rev 1020 | Rev 1034 | 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.  
  26. CanNode.prototype.isOnline = function()
  27. {
  28.     return this.myIsOnline;
  29. }
  30.  
  31. CanNode.prototype.start = function()
  32. {
  33.     var canMessage = new CanNMTMessage("nmt", "Start_App");
  34.     canMessage.setData("HardwareId", this.myHardwareId);
  35.     canMessage.send();
  36. }
  37.  
  38. CanNode.prototype.reset = function()
  39. {
  40.     var canMessage = new CanNMTMessage("nmt", "Reset");
  41.     canMessage.setData("HardwareId", this.myHardwareId);
  42.     canMessage.send();
  43. }
  44.  
  45. CanNode.prototype.startApplication = function()
  46. {
  47.     var canMessage = new CanNMTMessage("nmt", "Start_App");
  48.     canMessage.setData("HardwareId", this.myHardwareId);
  49.     canMessage.send();
  50. }
  51.  
  52. CanNode.prototype.handleHeartbeat = function(numberOfModules)
  53. {
  54.     if (numberOfModules)
  55.     {
  56.         this.myNumberOfModules = numberOfModules;
  57.     }
  58.    
  59.     if (this.myNumberOfModules == null || this.myNumberOfModules > this.myModules.length)
  60.     {
  61.         var canMessage = new CanMessage("mnmt", "To_Owner", "", 0, "List");
  62.         canMessage.setData("HardwareId", this.myHardwareId);
  63.         canMessage.send();
  64.     }
  65.    
  66.     this.onlineHandler();
  67. }
  68.  
  69. CanNode.prototype.startProgramming = function(hexData, progressCallback, isBios)
  70. {
  71.     if (isBios)
  72.     {
  73.         this.myProgrammingIsBios = isBios;
  74.     }
  75.     else
  76.     {
  77.         this.myProgrammingIsBios = false;
  78.     }
  79.    
  80.     this.myProgramming = true;
  81.     this.myProgrammingHex = hexData;
  82.     this.myProgrammingCallback = progressCallback;
  83.    
  84.     CanProgrammingNode = this;
  85.    
  86.     this.reset();
  87. }
  88.  
  89. CanNode.prototype.handleBiosStart = function(biosVersion, hasApplication)
  90. {
  91. //print("node was reset and bios just started, ver:" + biosVersion);
  92.     if (this.myProgramming)
  93.     {
  94.         this.myProgrammingHexAddress = this.myProgrammingHex.getAddrLower();
  95.         this.myProgrammingWantAck = ((this.myProgrammingHexAddress<<8)|(this.myProgrammingHexAddress>>8))&0xffff;
  96.    
  97.         var canMessage = new CanNMTMessage("nmt", "Pgm_Start");
  98.         canMessage.setData("HardwareId", this.myHardwareId);
  99.         canMessage.setData("Address0", this.myProgrammingHexAddress&0xff);
  100.         canMessage.setData("Address1", (this.myProgrammingHexAddress>>8)&0xff);
  101.         canMessage.setData("Address3", (this.myProgrammingHexAddress>>16)&0xff);
  102.         canMessage.setData("Address4", (this.myProgrammingHexAddress>>24)&0xff);
  103.         canMessage.send();
  104.         this.myProgrammingState = "DATA";
  105.        
  106.         this.myProgrammingCallback(true, "START", "Started programming of node");
  107.     }
  108. }
  109.  
  110. CanNode.prototype.handleNack = function(data)
  111. {
  112.     stopProgramming(true, "Failed, got NACK, sending reset");
  113.     this.reset();
  114.     if (false) 
  115.     {
  116.     }
  117. }
  118.  
  119. CanNode.prototype.handleAck = function(data)
  120. {
  121. //this.myProgrammingCallback(true, "DBG", "data: "+data+", myProgrammingWantAck: "+this.myProgrammingWantAck+"");
  122.    
  123.     if (data == this.myProgrammingWantAck) 
  124.     {
  125.  
  126.         switch (this.myProgrammingState)
  127.         {
  128.         case "DATA":
  129.             var offset = this.myProgrammingHexOffset;
  130.        
  131.             this.myProgrammingWantAck = ((offset<<8)|(offset>>8))&0xffff;
  132.             //var bytesLeft = this.myProgrammingHex.getAddrUpper() - (this.myProgrammingHexAddress+this.myProgrammingHexOffset);
  133.             var bytesLeft = this.myProgrammingHex.getLength() - this.myProgrammingHexOffset;
  134.            
  135.             //here we must handle the possibility that data is less then 48 bits
  136.             var canMessage = new CanNMTMessage("nmt", "Pgm_Data_48");
  137.             switch (bytesLeft)
  138.             {
  139.             case 1:
  140.                 canMessage = new CanNMTMessage("nmt", "Pgm_Data_8");
  141.                 break;
  142.             case 2:
  143.                 canMessage = new CanNMTMessage("nmt", "Pgm_Data_16");
  144.                 break;
  145.             case 3:
  146.                 canMessage = new CanNMTMessage("nmt", "Pgm_Data_24");
  147.                 break;
  148.             case 4:
  149.                 canMessage = new CanNMTMessage("nmt", "Pgm_Data_32");
  150.                 break;
  151.             case 5:
  152.                 canMessage = new CanNMTMessage("nmt", "Pgm_Data_40");
  153.                 break;
  154.             }
  155.            
  156.             canMessage.setData("Offset0", offset&0xff);
  157.             canMessage.setData("Offset1", (offset>>8)&0xff);
  158.             for (var i=0; i<bytesLeft && i<6; i++)
  159.             {
  160.                 switch (i)
  161.                 {
  162.                 case 0:
  163.                     canMessage.setData("Data0", this.myProgrammingHex.getByte(offset));
  164.                     break;
  165.                 case 1:
  166.                     canMessage.setData("Data1", this.myProgrammingHex.getByte(offset));
  167.                     break;
  168.                 case 2:
  169.                     canMessage.setData("Data2", this.myProgrammingHex.getByte(offset));
  170.                     break;
  171.                 case 3:
  172.                     canMessage.setData("Data3", this.myProgrammingHex.getByte(offset));
  173.                     break;
  174.                 case 4:
  175.                     canMessage.setData("Data4", this.myProgrammingHex.getByte(offset));
  176.                     break;
  177.                 case 5:
  178.                     canMessage.setData("Data5", this.myProgrammingHex.getByte(offset));
  179.                     break;
  180.                 }
  181.                 offset++;
  182.             }
  183.             canMessage.send();
  184.             this.myProgrammingHexOffset = offset;
  185.  
  186.             if (this.myProgrammingHexOffset >= this.myProgrammingHex.getLength()) {
  187.                 this.myProgrammingState = "END";
  188.             }
  189.            
  190.             this.myProgrammingCallback(true, "PROGRESS", this.myProgrammingHexOffset + ":" + this.myProgrammingHex.getLength());
  191.             break;
  192.        
  193.         case "END":
  194.             this.myProgrammingWantAck = ((this.myProgrammingHex.getCRC16()<<8)|(this.myProgrammingHex.getCRC16()>>8))&0xffff;
  195.        
  196.             var canMessage = new CanNMTMessage("nmt", "Pgm_End");
  197.             canMessage.send();
  198.  
  199.             this.myProgrammingState = "CRC";
  200.             break;
  201.            
  202.         case "CRC":
  203.             //is this a bios programming?
  204.             if (false)
  205.             {
  206.                 this.myProgrammingState = "COPY";
  207.                 this.myProgrammingCallback(true, "PROGRESS", "Start to copy bios to new location");
  208.                 var canMessage = new CanNMTMessage("nmt", "Pgm_Copy");
  209.                 canMessage.setData("Source", source);
  210.                 canMessage.setData("Destination", destination);
  211.                 canMessage.setData("Length", length);
  212.                 canMessage.send();
  213.                 this.stopProgramming();
  214.             }
  215.             else
  216.             {
  217.                 this.stopProgramming(true, "Done, sucessful");
  218.                 this.reset();
  219.             }
  220.             break;
  221.        
  222.         case "COPY":    //this will never occur, bios does not send ack for copy command, it just moves data in flash then reset itself
  223.             var source = ""; ///TODO: Fill in something here
  224.             var destination = ""; ///TODO: Fill in something here
  225.             var length = ""; ///TODO: Fill in something here
  226.            
  227.             this.myProgrammingWantAck = "";  ///TODO: Fill in something here
  228.        
  229.            
  230.             this.myProgrammingCallback(true, "END", ""); ///TODO: Fill in something meaningfull text
  231.             break;
  232.            
  233.         default:
  234.             break;
  235.         }
  236.     }
  237.     else
  238.     {
  239.         switch (this.myProgrammingState)
  240.         {
  241.         case "DATA":
  242.             //Fall through
  243.         case "END":
  244.             ///TODO: We got something that was not correct... we should abort
  245.             this.stopProgramming(true, "Failed to program, ack had wrong offset, expected data: "+this.myProgrammingWantAck+" got: "+data);
  246.             this.reset();
  247.             break;
  248.         case "CRC":
  249.             this.stopProgramming(true, "Failed to program, CRC not matching, expected data: "+this.myProgrammingWantAck+" got: "+data);
  250.             this.reset();
  251.             break;
  252.         case "COPY":    //this will never occur, bios does not send ack for copy command, it just moves data in flash then reset itself
  253.             break;
  254.         default:
  255.             break;
  256.         }
  257.     }
  258. }
  259.  
  260. CanNode.prototype.stopProgramming = function(status, text)
  261. {
  262.     if (status && text)
  263.     {
  264.         this.myProgrammingCallback(status, "STOP", text);
  265.     }
  266.  
  267.     this.myProgrammingIsBios = false;
  268.     this.myProgramming = false;
  269.     this.myProgrammingHex = new Array();
  270.     this.myProgrammingHexAddress = 0;
  271.     this.myProgrammingHexOffset = 0;
  272.     this.myProgrammingCallback = function() {};
  273.     this.myProgrammingWantAck = null;
  274.     this.myProgrammingState = "";
  275.    
  276.     CanProgrammingNode = null;
  277. }
  278.  
  279.  
  280.  
  281. CanNode.prototype.addService = function(sequenceNumber, service)
  282. {
  283.     this.myModules[sequenceNumber] = service;
  284.     service.setOnline();
  285. }
  286.  
  287. CanNode.prototype.onlineHandler = function()
  288. {
  289.     var date = new Date();
  290.     this.myHeartbeatTime = date.getTimestamp();
  291.  
  292.     if (!this.myIsOnline)
  293.     {
  294.         this.myIsOnline = true;
  295.  
  296.         log(uint2hex(this.myHardwareId, 32) + "> Node went online\n");
  297.        
  298.         for (var n in this.myModules)
  299.         {
  300.             this.myModules[n].setOnline();
  301.         }
  302.     }
  303. }
  304.  
  305. CanNode.prototype.checkOffline = function()
  306. {
  307.     if (this.myIsOnline)
  308.     {
  309.         var date = new Date();
  310.         if (this.myHeartbeatTime + 10 < date.getTimestamp())
  311.         {
  312.             this.setOffline();
  313.         }
  314.     }
  315. }
  316.  
  317. CanNode.prototype.setOffline = function()
  318. {
  319.     if (this.myIsOnline)
  320.     {
  321.         this.myIsOnline = false;
  322.  
  323.         log(uint2hex(this.myHardwareId, 32) + "> Node went offline\n");
  324.        
  325.         for (var n in this.myModules)
  326.         {
  327.             this.myModules[n].setOffline();
  328.         }
  329.     }
  330. }
  331.