|  |  |  | @ -17,6 +17,9 @@ namespace PHPModbus\Packet; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | use PHPModbus\IecType; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  |  |  * Builds/parses packet in Modbus TCP/IP format (http://www.simplymodbus.ca/TCP.htm) | 
			
		
	
		
			
				
					|  |  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  |  | class WriteMultipleCoilsPacket | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |     /** | 
			
		
	
	
		
			
				
					|  |  |  | @ -30,49 +33,25 @@ class WriteMultipleCoilsPacket | 
			
		
	
		
			
				
					|  |  |  |  |     public static function build($unitId, $reference, array $data) | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         $dataLen = 0; | 
			
		
	
		
			
				
					|  |  |  |  |         // build bool stream to the WORD array | 
			
		
	
		
			
				
					|  |  |  |  |         $data_word_stream = array(); | 
			
		
	
		
			
				
					|  |  |  |  |         $data_word = 0; | 
			
		
	
		
			
				
					|  |  |  |  |         $shift = 0; | 
			
		
	
		
			
				
					|  |  |  |  |         for ($i = 0, $len = count($data); $i < $len; $i++) { | 
			
		
	
		
			
				
					|  |  |  |  |             if ((($i % 8) === 0) && ($i > 0)) { | 
			
		
	
		
			
				
					|  |  |  |  |                 $data_word_stream[] = $data_word; | 
			
		
	
		
			
				
					|  |  |  |  |                 $shift = 0; | 
			
		
	
		
			
				
					|  |  |  |  |                 $data_word = 0; | 
			
		
	
		
			
				
					|  |  |  |  |                 $data_word |= (0x01 && $data[$i]) << $shift; | 
			
		
	
		
			
				
					|  |  |  |  |                 $shift++; | 
			
		
	
		
			
				
					|  |  |  |  |             } else { | 
			
		
	
		
			
				
					|  |  |  |  |                 $data_word |= (0x01 && $data[$i]) << $shift; | 
			
		
	
		
			
				
					|  |  |  |  |                 $shift++; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         $data_word_stream[] = $data_word; | 
			
		
	
		
			
				
					|  |  |  |  |         // show binary stream to status string | 
			
		
	
		
			
				
					|  |  |  |  | //        foreach ($data_word_stream as $d) { | 
			
		
	
		
			
				
					|  |  |  |  | //            $this->status .= sprintf("byte=b%08b\n", $d); | 
			
		
	
		
			
				
					|  |  |  |  | //        } | 
			
		
	
		
			
				
					|  |  |  |  |         // build data section | 
			
		
	
		
			
				
					|  |  |  |  |         $buffer1 = ''; | 
			
		
	
		
			
				
					|  |  |  |  |         foreach ($data_word_stream as $key => $dataitem) { | 
			
		
	
		
			
				
					|  |  |  |  |             $buffer1 .= IecType::iecBYTE($dataitem);   // register values x | 
			
		
	
		
			
				
					|  |  |  |  |             $dataLen += 1; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         list($pduData, $wordCount) = self::getDataConvertedToIecWords($data); | 
			
		
	
		
			
				
					|  |  |  |  |         $dataLen += $wordCount; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         // build body | 
			
		
	
		
			
				
					|  |  |  |  |         $buffer2 = ''; | 
			
		
	
		
			
				
					|  |  |  |  |         $buffer2 .= IecType::iecBYTE(15);             // FC 15 = 15(0x0f) | 
			
		
	
		
			
				
					|  |  |  |  |         $buffer2 .= IecType::iecINT($reference);      // refnumber = 12288 | 
			
		
	
		
			
				
					|  |  |  |  |         $buffer2 .= IecType::iecINT(count($data));      // bit count | 
			
		
	
		
			
				
					|  |  |  |  |         $buffer2 .= IecType::iecBYTE((count($data) + 7) / 8);       // byte count | 
			
		
	
		
			
				
					|  |  |  |  |         $pduHeader = ''; | 
			
		
	
		
			
				
					|  |  |  |  |         $pduHeader .= IecType::iecBYTE(15);             // FC 15 = 15(0x0f) | 
			
		
	
		
			
				
					|  |  |  |  |         $pduHeader .= IecType::iecINT($reference);      // refnumber = 12288 | 
			
		
	
		
			
				
					|  |  |  |  |         $pduHeader .= IecType::iecINT(count($data));      // bit count | 
			
		
	
		
			
				
					|  |  |  |  |         $pduHeader .= IecType::iecBYTE((count($data) + 7) / 8);       // byte count | 
			
		
	
		
			
				
					|  |  |  |  |         $dataLen += 6; | 
			
		
	
		
			
				
					|  |  |  |  |         // build header | 
			
		
	
		
			
				
					|  |  |  |  |         $buffer3 = ''; | 
			
		
	
		
			
				
					|  |  |  |  |         $buffer3 .= IecType::iecINT(mt_rand(0, 65000));   // transaction ID | 
			
		
	
		
			
				
					|  |  |  |  |         $buffer3 .= IecType::iecINT(0);               // protocol ID | 
			
		
	
		
			
				
					|  |  |  |  |         $buffer3 .= IecType::iecINT($dataLen + 1);    // length | 
			
		
	
		
			
				
					|  |  |  |  |         $buffer3 .= IecType::iecBYTE($unitId);        // unit ID | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         // return packet string | 
			
		
	
		
			
				
					|  |  |  |  |         return $buffer3 . $buffer2 . $buffer1; | 
			
		
	
		
			
				
					|  |  |  |  |         $mbapHeader = ''; | 
			
		
	
		
			
				
					|  |  |  |  |         $mbapHeader .= IecType::iecINT(mt_rand(0, 65000));   // transaction ID | 
			
		
	
		
			
				
					|  |  |  |  |         $mbapHeader .= IecType::iecINT(0);               // protocol ID | 
			
		
	
		
			
				
					|  |  |  |  |         $mbapHeader .= IecType::iecINT($dataLen + 1);    // length | 
			
		
	
		
			
				
					|  |  |  |  |         $mbapHeader .= IecType::iecBYTE($unitId);        // unit ID | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         return $mbapHeader . $pduHeader . $pduData; | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /** | 
			
		
	
	
		
			
				
					|  |  |  | @ -86,4 +65,32 @@ class WriteMultipleCoilsPacket | 
			
		
	
		
			
				
					|  |  |  |  |         return true; | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /** | 
			
		
	
		
			
				
					|  |  |  |  |      * @param array $data | 
			
		
	
		
			
				
					|  |  |  |  |      * @return array | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     private static function getDataConvertedToIecWords(array $data) | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         $data_word_stream = array(); | 
			
		
	
		
			
				
					|  |  |  |  |         $data_word = 0; | 
			
		
	
		
			
				
					|  |  |  |  |         $shift = 0; | 
			
		
	
		
			
				
					|  |  |  |  |         for ($i = 0, $len = count($data); $i < $len; $i++) { | 
			
		
	
		
			
				
					|  |  |  |  |             if ((($i % 8) === 0) && ($i > 0)) { | 
			
		
	
		
			
				
					|  |  |  |  |                 //shift to next word | 
			
		
	
		
			
				
					|  |  |  |  |                 $data_word_stream[] = $data_word; | 
			
		
	
		
			
				
					|  |  |  |  |                 $shift = 0; | 
			
		
	
		
			
				
					|  |  |  |  |                 $data_word = 0; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             $data_word |= (0x01 && $data[$i]) << $shift; | 
			
		
	
		
			
				
					|  |  |  |  |             $shift++; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         $data_word_stream[] = $data_word; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         $pduData = ''; | 
			
		
	
		
			
				
					|  |  |  |  |         foreach ($data_word_stream as $key => $dataitem) { | 
			
		
	
		
			
				
					|  |  |  |  |             $pduData .= IecType::iecBYTE($dataitem); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         return array($pduData, count($data_word_stream)); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | } |