• Facebook
  • Twitter
  • Reddit
  • StumbleUpon
  • Digg
  • email

# Copyright(C) 2007 VTT Technical Research Centre of Finland
#  
# This file is part of NOEN framework.
#  
# NOEN framework is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2.
#  
# NOEN framework is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
 
# TODO: 6 byte integer writin for nano seconds
 
import struct
 
# Protocol version
protocolVersion = 0x02
 
# IDs
initialBinary = 0xFF
projectChange = 0x00
input1 = 0x0A
input2 = 0x0B
input3 = 0x0C
outputType = 0x10
output1 = 0x11
output2 = 0x12
output3 = 0x13
 
# Endians
littleEndian = [0x00, '<']
bigEndian = [0xFF, '>']
 
# Time resolutions
nanoSeconds = 0x00
microSeconds = 0x01
milliSeconds = 0x02
seconds = 0x03
minutes = 0x04
timeTypes = ['Q','I','I','I','I']
#timeResolution = milliseconds
 
# Datatypes:
# boolean(1), 1 byte, 0x00 = false, 0x01 = true
# integer(2), 1 byte
# integer(3), 2 byte
# integer(4), 3 byte
# integer(5), 4 byte
# integer(6), 8 byte
# float(7), 4 byte
# teksti(8)
# binary(9)
dataTypeLengths = [0,1,1,2,3,4,8,4,0,0]
dataTypes = ['','b','b','h','BBB','i','i','f','s','s']
 
# formatInitialData
# Initial binary: <0xFF><Order><protocol version><L><Project name><L><Version>
# <L><Test case number><L><Target><L><Description><time resolution><time><nnn> 
def formatInitialData(project, version, testcaseNumber, target, description, timeResolution, time, id):
    format = bigEndian[1] + 'BBBB' + \
            str(len(project)) + 'sB' + \
            str(len(version)) + 'sB' + \
            str(len(testcaseNumber)) + 'sB' + \
            str(len(target)) + 'sB' + \
            str(len(description)) + 'sB' + 'IBBB'
    return struct.pack(format, initialBinary, bigEndian[0], protocolVersion,\
                       len(project), project,\
                       len(version), version,\
                       len(testcaseNumber), testcaseNumber,\
                       len(target), target,\
                       len(description), description,\
                       timeResolution,\
                       time, id[0], id[1], id[2])
 
# formatInputData
# <0x0A><input number><datatype number><L*><data><time>
def formatInputData(inputNumber,dataType,data,time,timeResolution):
    if dataType == 8 or dataType == 9:
        format = bigEndian[1] + 'BHBH' + str(len(data)) + 's' + timeTypes[timeResolution]
        #print "Number: " + str(inputNumber) + " Format: " + str(format)
        return struct.pack(format, input1, inputNumber,\
                           dataType, len(data), data, time)
    else:
        if dataType == 4:
            format = bigEndian[1] + 'BHB' + dataTypes[dataType] + timeTypes[timeResolution]
            #print "Number: " + str(inputNumber) + " Format: " + str(format)
            return struct.pack(format, input1, inputNumber,\
                               dataType, data[0],data[1],data[2], time)   
        else:
            format = bigEndian[1] + 'BHB' + dataTypes[dataType] + timeTypes[timeResolution]
            #print "Number: " + str(inputNumber) + " Format: " + str(format)
            return struct.pack(format, input1, inputNumber,\
                               dataType, data, time)        
 
# formatInput2Data
# <0x0B><input number><datatype number><number of inputs><data><time><data><time>
def formatInput2Data(firstInputNumber,dataType,dataTimes):
    #if dataType == 8 or dataType == 9:
    #    format = 'BHBH' + str(len(data)) + 'sI'
    #    return struct.pack(format, input1, inputNumber,\
    #                       dataType, len(data), data, time)
    #else:
    if dataType == 4:
        format = bigEndian[1] + 'BHBH'
        input2Data = struct.pack(format, input2, firstInputNumber,\
                               dataType, len(dataTimes)).rstrip('\n')
        format = bigEndian[1] + dataTypes[dataType] + 'I'
        for data,time in dataTimes:
            input2Data += struct.pack(format,data[0],data[1],data[2],time).rstrip('\n')
    else:
        format = bigEndian[1] + 'BHBH'
        input2Data = struct.pack(format, input2, firstInputNumber,\
                               dataType, len(dataTimes)).rstrip('\n')
        format = bigEndian[1] + dataTypes[dataType] + 'I'
        for data,time in dataTimes:
            input2Data += struct.pack(format,data,time).rstrip('\n')
    return input2Data
 
# formatInput3Data
# <0x0C><input number><datatype number><number of inputs><data><data><data><data>
def formatInput3Data(firstInputNumber,dataType,datas):
    #if dataType == 8 or dataType == 9:
    #    format = 'BHBH' + str(len(data)) + 'sI'
    #    return struct.pack(format, input1, inputNumber,\
    #                       dataType, len(data), data, time)
    #else:
    if dataType == 4:
        format = bigEndian[1] + 'BHBH'
        input3Data = struct.pack(format, input3, firstInputNumber,\
                               dataType, len(datas)).rstrip('\n')
        format = dataTypes[dataType]
        for data in datas:
            input3Data += struct.pack(format,data[0],data[1],data[2]).rstrip('\n')
    else:
        format = bigEndian[1] + 'BHBH'
        input3Data = struct.pack(format, input3, firstInputNumber,\
                               dataType, len(datas)).rstrip('\n')
        format = dataTypes[dataType]
        for data in datas:
            input3Data += struct.pack(format,data).rstrip('\n')
    return input3Data
 
# formatOutputType
# <0x10><output type number><L><output type name><datatype number>
def formatOutputType(outputTypeNumber,outputTypeName,dataType):
    format = bigEndian[1] + 'BBB' + str(len(outputTypeName)) + 'sB'
    return struct.pack(format,outputType,outputTypeNumber,len(outputTypeName),outputTypeName,dataType)
 
# formatOutputData
# <0x11><output number><output type><L*><data><time>
def formatOutput1Data(outputNumber,outputType,dataType,data,time):
    if dataType == 9 or dataType == 8:
        format = bigEndian[1] + 'BHBH' + str(len(data)) + 'sI'
        return struct.pack(format,output1,outputNumber,\
                           outputType,len(data),data,time)
    else:
        if dataType == 4:
            format = bigEndian[1] + 'BHB' + dataTypes[dataType] + 'I'
            return struct.pack(format,output1,outputNumber,\
                               outputType,data[0],data[1],data[2],time)
        else:
            format = bigEndian[1] + 'BHB' + dataTypes[dataType] + 'I'
            return struct.pack(format,output1,outputNumber,\
                               outputType,data,time)
 
# formatOutput2Data
# <0x12><output number><output type><number of outputs><data><time><data><time>
def formatOutput2Data(outputNumber,outputType,dataType,dataTimes):
    #if dataType == 9 or dataType == 8:
    #    format = 'BHBB' + str(len(data)) + 'sI'
    #    return struct.pack(format,output1,outputNumber,\
    #                       outputType,len(data),data,time)
    #else:
    if dataType == 4:
        format = bigEndian[1] + 'BHBH'
        output2Data = struct.pack(format,output2,outputNumber,\
                               outputType,len(dataTimes))
        format = bigEndian[1] + dataTypes[dataType] + 'I'
        for data,time in dataTimes:
            output2Data += struct.pack(format,data[0],data[1],data[2],time).rstrip('\n')
    else:
        format = bigEndian[1] + 'BHBH'
        output2Data = struct.pack(format,output2,outputNumber,\
                               outputType,len(dataTimes))
        format = bigEndian[1] + dataTypes[dataType] + 'I'
        for data,time in dataTimes:
            output2Data += struct.pack(format,data,time).rstrip('\n')
    return output2Data
 
# formatOutput2Data
# <0x12><output number><output type><number of outputs><data><time><data><time>
def formatOutput3Data(outputNumber,outputType,dataType,datas):
    #if dataType == 9 or dataType == 8:
    #    format = 'BHBB' + str(len(data)) + 'sI'
    #    return struct.pack(format,output1,outputNumber,\
    #                       outputType,len(data),data,time)
    #else:
    if dataType == 4:
        format = bigEndian[1] + 'BHBH'
        output3Data = struct.pack(format,output3,outputNumber,\
                               outputType,len(datas))
        format = bigEndian[1] + dataTypes[dataType]
        for data in datas:
            output3Data += struct.pack(format,data[0],data[1],data[2]).rstrip('\n')
    else:
        format = bigEndian[1] + 'BHBH'
        output3Data = struct.pack(format,output3,outputNumber,\
                               outputType,len(datas))
        format = bigEndian[1] + dataTypes[dataType]
        for data in datas:
            output3Data += struct.pack(format,data).rstrip('\n')
    return output3Data
 
def intToBytes(intValue):
    bytes = struct.pack('>I',intValue)
    bytes = struct.unpack('>BBBB',bytes)
    return bytes
 
def formatProjectChange(id):
    format = bigEndian[1] + 'BBBB'
    return struct.pack(format,projectChange,id[0],id[1],id[2])
 
# writeData
# opens binary file for writing and writes sample binaryfile
def writeData():
    binFile = file('binarySample.dat', 'wb')
    #binFile.write(struct.pack('>2sBH2s','AA',255,255,'AA'))
    #binFile.write(struct.pack('2sBHBH2s','TT',10,1,8,11,'TT'))
    binFile.write(formatInitialData('Project Name', '1.0.1', '1.1', 'Target', 'Description', microSeconds,12345,[3,2,1]).rstrip('\n'))
    binFile.write(formatInputData(1,8,'test text data',1234567890,microSeconds).rstrip('\n'))
    binFile.write(formatInitialData('Project 2 Name', '1.0.0', '1.11', 'Target2', 'Description2', nanoSeconds,12345,[3,2,2]).rstrip('\n'))
    binFile.write(formatProjectChange([3,2,1]).rstrip('\n'))
    binFile.write(formatInputData(2,7,1.234,123456789,microSeconds).rstrip('\n'))
    binFile.write(formatInput2Data(3,5,[[1,12345],[420,987654],[153,666],[144000,616],[715517,7331]]))
    binFile.write(formatInput3Data(8,5,[1,420,153,144000,715517]))
    binFile.write(formatInputData(13,4,[0,0,1],123456789,microSeconds).rstrip('\n'))
    binFile.write(formatInput2Data(14,4,[[[255,255,42],12345],[[0,0,255],852]]))
    binFile.write(formatInput3Data(16,4,[[127,255,255],[0,1,164]]))
    binFile.write(formatOutputType(5,'datarate',4).rstrip('\n'))
    binFile.write(formatOutputType(6,'Output text message',8).rstrip('\n'))
    binFile.write(formatOutputType(7,'3 byte integer',4).rstrip('\n'))
    binFile.write(formatOutputType(8,'1 byte integer',2).rstrip('\n'))
    binFile.write(formatOutputType(9,'2 byte int',3).rstrip('\n'))
    binFile.write(formatOutput1Data(1,6,8,'output text',1234566).rstrip('\n'))
    binFile.write(formatOutput1Data(2,3,5,9999,1234566).rstrip('\n'))
    binFile.write(formatOutput2Data(3,3,5,[[123,456],[789,101],[234,56789],[9854,45789],[10000,9899999]]))
    binFile.write(formatOutput3Data(8,9,3,[123,789,234,9876,1000]))
    binFile.write(formatOutput1Data(13,7,4,[147,255,0x2B],1234566).rstrip('\n'))
    binFile.write(formatOutput1Data(14,7,4,[0,0,1],1234567).rstrip('\n'))
    binFile.write(formatOutput1Data(15,7,4,[255,255,254],1234568).rstrip('\n'))
    binFile.write(formatOutput1Data(16,7,4,[128,0,1],1234569).rstrip('\n'))
    binFile.write(formatOutput1Data(17,8,2,-1,1234570).rstrip('\n'))
    binFile.write(formatOutput2Data(18,7,4,[[[255,255,42],12345],[[0,0,255],852]]))
    binFile.write(formatOutput3Data(20,7,4,[[255,255,42],[0,0,255]]))
    binFile.write(formatProjectChange([3,2,2]).rstrip('\n'))
    binFile.write(formatInputData(1,8,'nanoseconds test:2199023255552',2199023255552,nanoSeconds).rstrip('\n'))
    binFile.close()
    print 'binary data written!'
 
def writeTestBinary():
    binFile = file('binarySample.txt', 'wb')
    binFile.write(formatOutput3Data(8,3,2,[123,789,234,9876,1000]))
    print 'binary data written!'
 
def writeDataToRows():
    binFile = file('binarySample.txt', 'wb')
    #binFile.write(struct.pack('>2sBH2s','AA',255,255,'AA'))
    #binFile.write(struct.pack('2sBHBH2s','TT',10,1,8,11,'TT'))
    binFile.write(formatInitialData('Project Name', '1.0.1', '1.1', 'Target', 'Description', microSeconds,12345,[3,2,1]))
    binFile.write(formatInputData(1,8,'test text data',1234567890))
    binFile.write(formatInitialData('Project 2 Name', '1.0.0', '1.11', 'Target2', 'Description2', microSeconds,12345,[3,2,2]))
    binFile.write(formatProjectChange([3,2,1]))
    binFile.write(formatInputData(2,7,1.234,123456789))
    binFile.write(formatInput2Data(3,5,[[1,12345],[420,987654],[153,666],[144000,616],[715517,7331]]))
    binFile.write(formatInput3Data(3,5,[1,420,153,144000,715517]))
    binFile.write(formatOutputType(5,'datarate',4))
    binFile.write(formatOutputType(6,'Output text message',8))
    binFile.write(formatOutput1Data(1,6,8,'output text',1234566))
    binFile.write(formatOutput1Data(2,3,5,9999,1234566))
    binFile.write(formatOutput2Data(3,3,5,[[123,456],[789,101],[234,56789],[9854,45789],[10000,9899999]]))
    binFile.write(formatOutput3Data(3,3,5,[123,789,234,9876,1000]))
 
    binFile.close()
    print 'binary data written to rows!'
 
writeData()
#writeTestBinary()
#writeDataToRows()