"""LCM type definitions
This file automatically generated by lcm.
DO NOT MODIFY BY HAND!!!!
"""

"""
rdi_pd4_t.lcm
lcm definition that matches the binary data output message
generated by the PCDAS software that interfaces the rdi
dvl with the rest of the OI subsystem. 
http://www.teledynemarine.com/Documents/Brand%20Support/RD%20INSTRUMENTS/Technical%20Resources/Manuals%20and%20Guides/Workhorse/WorkHorse%20Commands%20and%20Output%20Data%20Format_Jun18.pdf
 Copyright 2019 MBARI

"""

from io import BytesIO
import struct

import oi

class rdi_pd4_t(object):

    __slots__ = ["time_unix_sec", "count_publish", "sender_id", "dvl_id", "datstr", "num_bytes_uint", "sysconfig", "xvelbtm_mms", "yvelbtm_mms", "zvelbtm_mms", "evelbtm_mms", "beam1_cm_uint", "beam2_cm_uint", "beam3_cm_uint", "beam4_cm_uint", "bottom_stat", "xvel_ref_mms", "yvel_ref_mms", "zvel_ref_mms", "evel_ref_mms", "ref_layer_start_dm_uint", "ref_layer_end_dm_uint", "ref_layer_status", "time_of_ping_hr", "time_of_ping_min", "time_of_ping_sec", "time_of_ping_hun", "built_in_test_uint", "speed_of_sound_ms_uint", "temperature_cdegC", "checksum_uint", "ktnav_uint", "num_doubles", "doubles"]

    __typenames__ = ["double", "int64_t", "string", "byte", "byte", "int16_t", "byte", "int16_t", "int16_t", "int16_t", "int16_t", "int16_t", "int16_t", "int16_t", "int16_t", "byte", "int16_t", "int16_t", "int16_t", "int16_t", "int16_t", "int16_t", "byte", "byte", "byte", "byte", "byte", "int16_t", "int16_t", "int16_t", "int16_t", "int16_t", "int16_t", "oi.double_t"]

    __dimensions__ = [None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, ["num_doubles"]]

    def __init__(self):
        self.time_unix_sec = 0.0
        """
        Time since Unix Epoch
        LCM Type: double
        """

        self.count_publish = 0
        """
        LCM publish count
        LCM Type: int64_t
        """

        self.sender_id = ""
        """
        Self identifier for sender.
        LCM Type: string
        """

        self.dvl_id = 0
        """ LCM Type: byte """
        self.datstr = 0
        """
        DVL id 
        LCM Type: byte
        """

        self.num_bytes_uint = 0
        """
        data structure 0 = PD4, 1 = PD5
        Contains the number of bytes sent in this data structure, 
        not including the final check- sum.
        
        LCM Type: int16_t
        """

        self.sysconfig = 0
        """
        number of ytes in this structure
        BIT 76543210 
        00xxxxxx BEAM-COORDINATE VELOCITIES 
        01xxxxxx INSTRUMENT-COORDINATE VELOCITIES 
        10xxxxxx SHIP-COORDINATE VELOCITIES 
        11xxxxxx EARTH-COORDINATE VELOCITIES
        xx0xxxxx TILT INFORMATION NOT USED IN CALCULATIONS 
        xx1xxxxx TILT INFORMATION USED IN CALCULATIONS 
        xxx0xxxx 3-BEAM SOLUTIONS NOT COMPUTED
        xxx1xxxx 3-BEAM SOLUTIONS COMPUTED 
        xxxxx010 300-kHz DVL
        xxxxx011 600-kHz DVL
        xxxxx100 1200-kHz DVL 
        
        LCM Type: byte
        """

        self.xvelbtm_mms = 0
        """
        
        These fields contain the velocity of the vessel in relation to the 
        bottom in mm/s. Positive values indicate vessel motion to east (X), 
        north (Y), and up (Z). LSD = 1 mm/s (see NOTES at end of this table)
        
        LCM Type: int16_t
        """

        self.yvelbtm_mms = 0
        """ LCM Type: int16_t """
        self.zvelbtm_mms = 0
        """ LCM Type: int16_t """
        self.evelbtm_mms = 0
        """ LCM Type: int16_t """
        self.beam1_cm_uint = 0
        """
        These fields contain the vertical range from the ADCP to the bottom 
        as determined by each beam. This vertical range does not compensate 
        for the effects of pitch and roll. When a bottom detection is bad, 
        the field is set to zero.
        Scaling: LSD = 1 centimeter; Range = 0 to 65535 cm
        
        LCM Type: int16_t
        """

        self.beam2_cm_uint = 0
        """ LCM Type: int16_t """
        self.beam3_cm_uint = 0
        """ LCM Type: int16_t """
        self.beam4_cm_uint = 0
        """ LCM Type: int16_t """
        self.bottom_stat = 0
        """
        This field shows the status of bottom-referenced correlation and 
        echo amplitude data. Convert to binary and interpret as follows.
        A zero code indicates status is OK.
        BIT 76543210
        1xxxxxxx BEAM 4 LOW ECHO AMPLITUDE
        x1xxxxxx BEAM 4 LOW CORRELATION
        xx1xxxxx BEAM 3 LOW ECHO AMPLITUDE
        xxx1xxxx BEAM 3 LOW CORRELATION
        xxxx1xxx BEAM 2 LOW ECHO AMPLITUDE
        xxxxx1xx BEAM 2 LOW CORRELATION
        xxxxxx1x BEAM 1 LOW ECHO AMPLITUDE
        xxxxxxx1 BEAM 1 LOW CORRELATION
        
        LCM Type: byte
        """

        self.xvel_ref_mms = 0
        """
        These fields contain the velocity of the vessel in relation to 
        the water-mass reference layer in mm/s. The setting of the 
        EX-command (Coordinate Transformation) determines how the 
        WorkHorse references the velocity data. 
        
        LCM Type: int16_t
        """

        self.yvel_ref_mms = 0
        """ LCM Type: int16_t """
        self.zvel_ref_mms = 0
        """ LCM Type: int16_t """
        self.evel_ref_mms = 0
        """ LCM Type: int16_t """
        self.ref_layer_start_dm_uint = 0
        """
        These fields contain the starting boundary (near surface) and 
        the ending boundary (near bottom) of the water-mass reference 
        layer (BL command). If the minimum size field is zero, the 
        ADCP does not calculate reference-layer data.
        Scaling: LSD = 1 dm; Range = 0-9999 dm
        
        LCM Type: int16_t
        """

        self.ref_layer_end_dm_uint = 0
        """
        decimeters
        LCM Type: int16_t
        """

        self.ref_layer_status = 0
        """
        decimeters
        This field shows the status of reference layer depth and 
        correlation data. Convert to bi- nary and interpret as follows. 
        A zero code indicates status is OK.
        BIT 76543210
        xxx1xxxx ALTITUDE IS TOO SHALLOW
        xxxx1xxx BEAM 4 LOW CORRELATION
        xxxxx1xx BEAM 3 LOW CORRELATION
        xxxxxx1x BEAM 2 LOW CORRELATION
        xxxxxxx1 BEAM 1 LOW CORRELATION
        
        LCM Type: byte
        """

        self.time_of_ping_hr = 0
        """
        These fields contain the time of the first ping of the 
        current ensemble
        
        LCM Type: byte
        """

        self.time_of_ping_min = 0
        """ LCM Type: byte """
        self.time_of_ping_sec = 0
        """ LCM Type: byte """
        self.time_of_ping_hun = 0
        """ LCM Type: byte """
        self.built_in_test_uint = 0
        """
        These fields contain the results of the ADCP’s Built-in 
        Test function. A zero code indicates a successful BIT result.
        BYTE 40  BYTE 41 (BYTE 41 RESERVED FOR FUTURE USE)
        1xxxxxxx xxxxxxxx = RESERVED
        x1xxxxxx xxxxxxxx = RESERVED
        xx1xxxxx xxxxxxxx = RESERVED
        xxx1xxxx xxxxxxxx = DEMOD 1 ERROR
        xxxx1xxx xxxxxxxx = DEMOD 0 ERROR
        xxxxx1xx xxxxxxxx = RESERVED
        xxxxxx1x xxxxxxxx = DSP ERROR
        xxxxxxx1 xxxxxxxx = RESERVED
        
        LCM Type: int16_t
        """

        self.speed_of_sound_ms_uint = 0
        """ LCM Type: int16_t """
        self.temperature_cdegC = 0
        """
        meters per second
        LCM Type: int16_t
        """

        self.checksum_uint = 0
        """
        centidegrees Celsius
        This field contains a modulo 65536 checksum. The ADCP 
        computes the checksum by sum- ming all the bytes in 
        the output buffer excluding the checksum. NOTE: This 
        field contains the checksum only when the PD4 command 
        is used. If PD5 is used, the remaining bytes are 
        explained in Table 44.
        
        LCM Type: int16_t
        """

        self.ktnav_uint = 0
        """ LCM Type: int16_t """
        self.num_doubles = 0
        """ LCM Type: int16_t """
        self.doubles = []
        """ LCM Type: oi.double_t[num_doubles] """

    def encode(self):
        buf = BytesIO()
        buf.write(rdi_pd4_t._get_packed_fingerprint())
        self._encode_one(buf)
        return buf.getvalue()

    def _encode_one(self, buf):
        buf.write(struct.pack(">dq", self.time_unix_sec, self.count_publish))
        __sender_id_encoded = self.sender_id.encode('utf-8')
        buf.write(struct.pack('>I', len(__sender_id_encoded)+1))
        buf.write(__sender_id_encoded)
        buf.write(b"\0")
        buf.write(struct.pack(">BBhBhhhhhhhhBhhhhhhBBBBBhhhhhh", self.dvl_id, self.datstr, self.num_bytes_uint, self.sysconfig, self.xvelbtm_mms, self.yvelbtm_mms, self.zvelbtm_mms, self.evelbtm_mms, self.beam1_cm_uint, self.beam2_cm_uint, self.beam3_cm_uint, self.beam4_cm_uint, self.bottom_stat, self.xvel_ref_mms, self.yvel_ref_mms, self.zvel_ref_mms, self.evel_ref_mms, self.ref_layer_start_dm_uint, self.ref_layer_end_dm_uint, self.ref_layer_status, self.time_of_ping_hr, self.time_of_ping_min, self.time_of_ping_sec, self.time_of_ping_hun, self.built_in_test_uint, self.speed_of_sound_ms_uint, self.temperature_cdegC, self.checksum_uint, self.ktnav_uint, self.num_doubles))
        for i0 in range(self.num_doubles):
            assert self.doubles[i0]._get_packed_fingerprint() == oi.double_t._get_packed_fingerprint()
            self.doubles[i0]._encode_one(buf)

    @staticmethod
    def decode(data: bytes):
        if hasattr(data, 'read'):
            buf = data
        else:
            buf = BytesIO(data)
        if buf.read(8) != rdi_pd4_t._get_packed_fingerprint():
            raise ValueError("Decode error")
        return rdi_pd4_t._decode_one(buf)

    @staticmethod
    def _decode_one(buf):
        self = rdi_pd4_t()
        self.time_unix_sec, self.count_publish = struct.unpack(">dq", buf.read(16))
        __sender_id_len = struct.unpack('>I', buf.read(4))[0]
        self.sender_id = buf.read(__sender_id_len)[:-1].decode('utf-8', 'replace')
        self.dvl_id, self.datstr, self.num_bytes_uint, self.sysconfig, self.xvelbtm_mms, self.yvelbtm_mms, self.zvelbtm_mms, self.evelbtm_mms, self.beam1_cm_uint, self.beam2_cm_uint, self.beam3_cm_uint, self.beam4_cm_uint, self.bottom_stat, self.xvel_ref_mms, self.yvel_ref_mms, self.zvel_ref_mms, self.evel_ref_mms, self.ref_layer_start_dm_uint, self.ref_layer_end_dm_uint, self.ref_layer_status, self.time_of_ping_hr, self.time_of_ping_min, self.time_of_ping_sec, self.time_of_ping_hun, self.built_in_test_uint, self.speed_of_sound_ms_uint, self.temperature_cdegC, self.checksum_uint, self.ktnav_uint, self.num_doubles = struct.unpack(">BBhBhhhhhhhhBhhhhhhBBBBBhhhhhh", buf.read(51))
        self.doubles = []
        for i0 in range(self.num_doubles):
            self.doubles.append(oi.double_t._decode_one(buf))
        return self

    @staticmethod
    def _get_hash_recursive(parents):
        if rdi_pd4_t in parents: return 0
        newparents = parents + [rdi_pd4_t]
        tmphash = (0xfb158a278c08889d+ oi.double_t._get_hash_recursive(newparents)) & 0xffffffffffffffff
        tmphash  = (((tmphash<<1)&0xffffffffffffffff) + (tmphash>>63)) & 0xffffffffffffffff
        return tmphash
    _packed_fingerprint = None

    @staticmethod
    def _get_packed_fingerprint():
        if rdi_pd4_t._packed_fingerprint is None:
            rdi_pd4_t._packed_fingerprint = struct.pack(">Q", rdi_pd4_t._get_hash_recursive([]))
        return rdi_pd4_t._packed_fingerprint

    def get_hash(self):
        """Get the LCM hash of the struct"""
        return struct.unpack(">Q", rdi_pd4_t._get_packed_fingerprint())[0]

