import netw
from micropython import const
import ustruct
import vts

class Sys_Info():
    hardware_info = netw.get_hwmodule_info()
    model = hardware_info.model.replace('"', '')
    model_firmware = hardware_info.version.replace('"', '')

class NetError(Exception):
    pass

class HardwareError(Exception):
    pass

class FirmwareError(Exception):
    pass

class Network():
    def __init__(self):
        self.devices = {}
        self.addr_channel_id = {}
        self.busy = False
        netw.set_callback(self._resp_loop)
        
    def cmd(self, s): # calls the command to be performed
        netw.get_messages().clear()
        netw.tx_msg_edm(s, netw.UBX_EDM_CMD_AT_REQ)
        print("Sent: ", s)

    def send_cmd(self, bytearray_msg):
        netw.tx_msg_edm(bytes(bytearray_msg).decode(), netw.UBX_EDM_CMD_DATA)
    
    def send_text(self, text, channel_id):
        message = bytearray()
        message.append(int(channel_id))
        message.extend(text)
        self.send_cmd(message)
    
    # ---------- Calls this if it doesn't know what the command is ---------- #
    def AT_default_resp(self, b):
        print("AT COMMAND DOESN'T EXIST: {}".format(b))

    # ---------- gets all message callbacks ---------- #
    def _resp_loop(self):
        resp = netw.get_messages().pop()
        print(resp)
        msg_type = resp.type
        msg_id = resp.id
        msg_len = resp.len
        msg = resp.msg

        if msg_id == netw.UBX_EDM_ID_AT:
            msg = resp.msg.decode('utf-8').strip()
            AT_call = msg.split(':')[0].replace('+','')
            if AT_call == 'OK':
                print("COMMAND ACKNOWLEDGED")
            else:
                self.__AT_commands.get(AT_call, self.AT_default_resp)(msg)

        elif msg_id == netw.UBX_EDM_ID_DATA:
            if msg_type == netw.UBX_EDM_TYPE_EVENT:
                self.__receive_text_msg(resp)
        
        elif msg_id == netw.UBX_EDM_ID_CONNECT:
            if msg_type == netw.UBX_EDM_TYPE_EVENT:
                self.__log_device_connect(resp)
        
        elif msg_id == netw.UBX_EDM_ID_DISCONNECT:
            if msg_type == netw.UBX_EDM_TYPE_EVENT:
                self.__log_device_disconnect(resp)

        # ---------- gets all message callbacks ---------- #
        # elif msg_id == netw.UBX_EDM_ID_CONNECT:
        #     if msg_type == netw.UBX_EDM_TYPE_EVENT:
        #         self.__log_device_connect(resp)

        # elif msg_id == netw.UBX_EDM_ID_DATA:
        #     if msg_type == netw.UBX_EDM_TYPE_EVENT:
        #         self.receiving_data = True
        #         if type(self) is WiFi:
        #             self.HTTP.data_received = self.HTTP.data_received + msg.decode('utf-8').strip()
        #         elif type(self) is MQTT_client:
        #             self.MQTT_message = msg.decode('utf-8').strip()
        #             print('MQTT MSG: '+ self.MQTT_message)

        # if self.receiving_data == False:
        #     self.receiving_data = None
        #     if type(self) is WiFi:
        #         self.HTTP.get_HTTP_msg()
        #     elif type(self) is MQTT_client:
        #         # self.show_message()
        #         pass

BT_MODE_DISC_OFF                = const(1)
BT_MODE_DISC_LIMITED            = const(2)
BT_MODE_DISC_ON                 = const(3)

BT_MODE_CONN_OFF                = const(1)
BT_MODE_CONN_ON                 = const(2)

BT_MODE_PAIR_OFF                = const(1)
BT_MODE_PAIR_ON                 = const(2)

BT_MODE_SEC_DISABLED            = const(1)
BT_MODE_SEC_DEFAULT             = const(2)
BT_MODE_SEC_DISPLAY_PASSKEY     = const(3)
BT_MODE_SEC_CONFIRM             = const(4)
BT_MODE_SEC_ENTER_PASSKEY       = const(5)

class Bluetooth(Network):

    __bond_incorrect_reasons = {
        1:'due to timeout.', 
        2:'because authentication or pairing failed. Often due to incorrect passkey.', 
        3:'because the protection against Man-In-The-Middle attack could not be guaranteed; the generated link key was too weak.',
        4:'because one of the peers does not support FIPS mode.'
    }

    __discoverable_modes = {
        1:'GAP non-discoverable mode',
        2:'GAP limited discoverable mode',
        3:'GAP general discoverable mode'
    }

    def __init__(self):
        super().__init__()
        self.bt_name =  None
        self.bt_MAC_address = None

        self.devices = {} # name : address
        self.addr_peer_handle = {} # address : peer handle
        self.addr_channel_id = {} # address : channel id
        
        self.text_messages = [None]*20
        self.__text_messages_circle_counter = 0

        self.__AT_commands = {
            'UBTLN'   :   self.__receive_init_name, 
            'UMLA'    :   self.__receive_init_MAC_address, 
            'UBTI'    :   self.__process_scan,
            'UUBTB'   :   self.__check_bonded,
            'UBTBD'   :   self.__receive_bonded_devices,
            'UUDPD'   :   self.__receive_disconnected_devices,
            'UUDPC'   :   self.__receive_connected_devices
        }

        self._get_init_name()
        self._get_init_MAC_address()

    ###############################################################
    ########################### PRIVATE ###########################
    ###############################################################
    # ---------- Used to get a key from val ---------- #
    def __get_keys_from_value(self, d, val):
        return [key for key, v in d.items() if v == val]

    def __receive_init_name(self, resp_msg):
        msg = resp_msg.split(':')
        self.bt_name = msg[1]
    
    def __receive_init_MAC_address(self, resp_msg):
        msg = resp_msg.split(':')
        self.bt_MAC_address = msg[1].split('\r')[0]

    # ---------- processes the scan ---------- #
    def __process_scan(self, resp_msg): # gets all messages and processes them
        device_split = resp_msg.split(",")
        self.devices[device_split[3].replace('"', '')] = device_split[0].split(":")[1][:-1]

    # ---------- gets a data message ---------- #
    def __receive_text_msg(self, resp):
        resp_msg = resp.msg.decode('utf-8').strip()[1:]
        if self.__text_messages_circle_counter > 19:
            self.__text_messages_circle_counter = 0
        self.text_messages[self.__text_messages_circle_counter] = resp_msg
        self.__text_messages_circle_counter +=1
        print("MESSAGE: {}".format(resp_msg))
    
    def __receive_bonded_devices(self, device):
        print("BONDED DEVICES: {}".format(device))

    # ---------- Checks the connected device ---------- #
    def __receive_connected_devices(self, resp_msg):
        peer_handle = resp_msg.split(':')[1].split(',')[0]
        device_address = resp_msg.split(':')[1].split(',')[3]
        self.addr_peer_handle[device_address[:-1]] = peer_handle

    # ---------- Checks the disconnect device ---------- #
    def __receive_disconnected_devices(self, device):
        # print("DISCONNECT")
        pass

    # ---------- Gets and processes a connection ---------- #
    def __log_device_connect(self, device):
        channel_id = device.msg[0]
        device_address = ''
        for character in device.msg[3:9]:
            hex_val = hex(character).replace('0x', '')
            print('HEX VAL = {}'.format(hex_val))
            if len(hex_val) < 2:
                hex_val = '0'+hex_val
            device_address = device_address + hex_val.upper()
        self.addr_channel_id[device_address] = channel_id
        print("CONNECTED DEVICES: {}".format(self.addr_channel_id))

    # ---------- Gets and processes a disconnect ---------- #
    def __log_device_disconnect(self, device):
        channel_id = device.msg[0]
        self.addr_channel_id.pop(self._get_address_from_channel_id(channel_id))

    # ---------- checks if connected to any bluetooth device ---------- #
    def __check_bonded(self, resp_msg):
        msg = resp_msg.split(':')
        bond_event_status = int(msg[1].split(',')[1])
        if bond_event_status == 0:
            print("Bonding Succesful")
        else:
            raise NetError("Bonding Error "+Bluetooth.__bond_incorrect_reasons[bond_event_status])
        
    ###############################################################
    ########################## PROTECTED ##########################
    ###############################################################
    # ---------- gets the initial message ---------- #
    def _get_init_name(self):
        self.cmd('AT+UBTLN?')
        
    # ---------- gets the initial MAC address ---------- #
    def _get_init_MAC_address(self):
        self.cmd('AT+UMLA=1')

    # ---------- gets the bluetooth address ---------- #
    def _get_address_from_name(self,name):
        try:
            return self.devices[name]
        except KeyError:
            print("Device not found")

    # ---------- gets the bluetooth address ---------- #
    def _get_name_from_address(self,address):
        return self.__get_keys_from_value(self.devices, address)[0]

    # ---------- gets the address from the channel_id ---------- #
    def _get_address_from_channel_id(self,channel_id):
        return self.__get_keys_from_value(self.addr_channel_id, channel_id)[0]

    # ---------- gets the channel_id from the address ---------- #
    def _get_channel_id_from_address(self,address):
        try:
            return self.addr_channel_id[address]
        except KeyError:
            print("Address not found")

    # ---------- gets the address from the peer_handle ---------- #
    def _get_address_from_peer_handle(self, peer_handle):
        return self.__get_keys_from_value(self.addr_peer_handle, peer_handle)[0]
    
    # ---------- gets the peer_handle from the address ---------- #
    def _get_peer_handle_from_address(self, address):
        try:
            return self.addr_peer_handle[address]
        except KeyError:
            print("Address not found")

    ###############################################################
    ########################### PUBLIC ############################
    ###############################################################
    # ---------- sets the name for the VBOX Touch device to appear as ---------- #
    def set_bt_name(self, name):
        self.cmd('AT+UBTLN='+name) # Write name
        self.cmd('AT&W') # Write name to start up database?
        self.bt_name = name

    # ---------- Scan for bluetooth devices ---------- #
    def scan(self): # call the scan command
        self.cmd('AT+UBTI=1,'+str(10000)) # 10s scan

    # ---------- Controls the pairing with other devices ---------- #
    def pairing(self, security=BT_MODE_SEC_DEFAULT, pairing=BT_MODE_PAIR_ON,
                        discoverability=BT_MODE_DISC_ON, connectability=BT_MODE_CONN_ON): # By default it will enable pairing
        #may require re-calling after a BT disconnect as accepted connections set pairing mode to disabled
        self.cmd('AT+UBTSM={}'.format(security)) #set Security Mode
        self.cmd('AT+UBTDM={}'.format(discoverability)) #set Discoverability
        self.cmd('AT+UBTCM={}'.format(connectability)) #set Connectability Mode
        self.cmd('AT+UBTPM={}'.format(pairing)) #set Pairing Mode

    # ---------- shows the text messages ---------- #
    def show_text_messages(self):
        for x in self.text_messages:
            print(x, end = ' ')
        print('\n')

    # ---------- clears the text messages ---------- #
    def clear_text_messages(self):
        for i in range (0, len(self.text_messages)):
            self.text_messages[i] = None

    # ---------- sends a message ---------- #
    def send_to_connected(self, data, device_name):
        channel_id = self._get_channel_id_from_address(self._get_address_from_name(device_name))
        self.send_text(data, channel_id)

    # ---------- Checks devices bonded ---------- #
    def get_bonded_devices(self):
        self.cmd('AT+UBTBD')

    # ---------- Creates a list of [channel_id, address, name] for each connected device ---------- #
    def get_connected_devices_dict(self):
        connected_devices = []
        for key in self.devices:
            try:
                channel_id = self.addr_channel_id[self.devices[key]]
                address = self.devices[key]
                device_name = key
                connected_devices.extend([channel_id,address,device_name])
            except KeyError:
                pass

        return connected_devices

    # ---------- bonds to a device ---------- #
    def bond_to_device(self, device):
        self.cmd('AT+UBTB={}'.format(self._get_address_from_name(device)))
    
    # ---------- unbonds to a device ---------- #
    def unbond_device(self, device):
        self.cmd('AT+UBTUB={}'.format(self._get_address_from_name(device)))

    # ---------- connects to a device ---------- #
    def peer_connect(self, device):
        print(self.addr_peer_handle)
        address = self._get_address_from_name(device)
        peer_handle = self._get_peer_handle_from_address(address)
        if peer_handle == None:
            self.cmd('AT+UDCP=spp://{}p/'.format(address))
        else:
            self.cmd('AT+UDCP=spp://{}:{}/'.format(address, self._get_peer_handle_from_address(address)))

    # ---------- disconnects to a device ---------- #
    def peer_disconnect(self, device):
        address = self._get_address_from_name(device)
        self.cmd('AT+UDCPC={}'.format(self._get_peer_handle_from_address(address)))

    def send_MQTT_request(self, device_name, type='sub', client_id='', username='your_username', password='your_password', topic='my/test/topic'):
        msg = '{}:{},{},{},{},{}'.format(self.bt_MAC_address, type, client_id, username, password, topic)
        self.send_to_connected(msg, device_name)


AUTH_OPEN     = 1
AUTH_WPA_WPA2 = 2
AUTH_LEAP     = 3
AUTH_PEAP     = 4

IP_STATIC = 1
IP_DHCP   = 2

class WiFi(Network):
    authentication_types = {
        32  : 'Shared Secret',
        16  : 'PSK',
        8   : 'EAP',
        4   : 'WPA',
        2   : 'WPA2',
        1   : 'WPA3',
    }
    
    cipher_types = {
        8  : 'WEP64',
        4  : 'WEP128',
        2  : 'TKIP',
        1  : 'AES/CCMP',
    }

    network_status_ids = {
        0   : 'Hardware_Address', 
        1   : 'Network_Status',
        2   : 'Interface_Type',
        101 : 'IPv4_Address',
        102 : 'Subnet_Mask',
        103 : 'Gateway',
        104 : 'Primary_DNS',
        105 : 'Seconday_DNS',
        201 : 'IPv6_link_local_address',
        210 : '210_IPv6_Address',
        211 : '211_IPv6_Address',
        212 : '212_IPv6_Address',
    }

    def __new__(cls, *args, **kwargs):
        if Sys_Info.model == 'NINA-B2':
            raise HardwareError("Network Component cannot access WiFi")
        else:
            return object.__new__(cls)

    def __init__(self):
        super().__init__()
        self.get_WiFi_MAC_address()
        self.receiving_data = None
        self.fully_connected = False
        self.channel_id = None

        self.network_status = {}
        self.ssid_to_bssid = {}
        self.bssid_info = {}
        self.configured_profiles = {}
        self.connection_established = False
        self.is_peer_connected = False

        self.__AT_commands = {
            'UWSCAN'      :   self.__process_scan,
            'UWAPMACADDR' :   self.__receive_WiFi_MAC_address,
            'UNSTAT'      :   self.__check_full_connection_response,
            'UUWLE'       :   self.__wifi_connection_established,
            'UUWLD'       :   self.__wifi_disconnection,
            'UUDPD'       :   self.__receive_peer_disconnect,
            'UUNU'        :   self.__wifi_network_up,
        }

    ###############################################################
    ########################### PRIVATE ###########################
    ###############################################################

    def __wifi_connection_established(self, resp):
        self.connection_established = True

    def __wifi_disconnection(self, resp):
        self.connection_established = False

    # ---------- Gets the WiFi up response string ---------- # 
    def __wifi_network_up(self, resp_msg):
        self.fully_connected = False
        self.network_interface_id = resp_msg.split(':')[1]
        self.check_full_connection()

    def __check_full_connection_response(self, resp_msg):
        if self.fully_connected == True:
            return
        messages = resp_msg.split('\r\n+UNSTAT:{},'.format(self.network_interface_id))[1:] # splits all the +UNSTAT responses up
        for msg in messages: # gets each string of the messages  
            msg_lst = msg.split(',') # splits them by their type and data
            if int(msg_lst[0]) == 101: # checks if it is the IP type has been acquired as this happens last
                if msg_lst[1] != '0.0.0.0': # check that the IP has changed
                    self.fully_connected = True

            self.network_status[WiFi.network_status_ids[int(msg_lst[0])]] = msg_lst[1]

        print(self.network_status)


    def __receive_WiFi_MAC_address(self,resp_msg):
        MAC_address = resp_msg.split(':')[1]
        self.WiFi_MAC_address = MAC_address


    def __process_scan(self, resp_msg): # Receives the data from the WiFi scan command and processes it
        msg = resp_msg.split(':')[1].split(',')
        bssid = msg[0]
        op_mode = msg[1]
        ssid = msg[2].replace('"','')
        channel = msg[3]
        rssi = msg[4]
        authentication_suites = msg[5]
        unicast_ciphers = msg[6]
        group_ciphers = msg[7]
        print('MSG: BSSID = {}, OP_MODE = {}, SSID = {}, CHANNEL = {}, RSSI = {}, AUTHENTICATION_SUITES = {}, UNICAST_CIPHERS = {}, GROUP_CIPHERS = {}'.format(bssid, op_mode, ssid, channel, rssi, authentication_suites, unicast_ciphers, group_ciphers))
        self.ssid_to_bssid[ssid] = bssid
        self.bssid_info[bssid] = [op_mode, channel, rssi, authentication_suites, unicast_ciphers, group_ciphers]


    def __log_device_connect(self, resp):
        self.channel_id = resp.msg[0]


    def __receive_peer_disconnect(self, resp):
        self.receiving_data = False

    ###############################################################
    ########################## PROTECTED ##########################
    ###############################################################


    ###############################################################
    ########################### PUBLIC ############################
    ###############################################################
    # ---------- Checks whether there has been a successful connection ---------- #
    def check_full_connection(self):
        self.cmd('AT+UNSTAT={}'.format(self.network_interface_id))

    # ---------- Gets the MAC Address of the WiFi ---------- #
    def get_WiFi_MAC_address(self):
        self.cmd('AT+UWAPMACADDR')

    # ---------- Scans for WiFi ---------- #
    def scan_wifi(self):
        self.cmd('AT+UWSCAN')

    # ---------- Sets up the profile for a WiFi connection ---------- #
    def wifi_setup_connect(self, ssid, password='', auth=AUTH_WPA_WPA2, ipmode=IP_DHCP, always_active=False):
        profile = 0
        for key, item in self.configured_profiles.items():
            if profile > 9:
                profile = 0
                print("Overwriting Profile at value 0")
                break
            elif profile != item:
                break
            profile+=1
        
        self.disconnect_from_wifi(profile)
        self.cmd('AT+UWSC={},0,{:d}'.format(profile, always_active)) # decides if the station is active on start up.
        self.cmd('AT+UWSC={},2,"{}"'.format(profile, ssid)) # Sets the ssid of the wifi
        # self.cmd('AT+UWSC={},3,"{}"'.format(profile, self.ssid_to_bssid[ssid])) # Sets the bssid
        self.cmd('AT+UWSC={},5,{}'.format(profile, auth)) # Shows the authentication type

        if auth != AUTH_OPEN: # If it requires a password
            self.cmd('AT+UWSC={},{},"{}"'.format(profile,  
                8 if AUTH_WPA_WPA2 == auth else 9, # Gives the password type
                password)) # password
        self.cmd('AT+UWSC={},100,{}'.format(profile, ipmode)) # Sets the way to get the IP address. Static or DHCP
        self.cmd('AT+UWSCA={},1'.format(profile)) # Store the profile
        self.configured_profiles[ssid] = profile
    
        return profile

    # ---------- Connect to WiFi ---------- #
    def connect_to_wifi(self, profile):
        self.cmd('AT+UWSCA={},3'.format(profile)) # Activate profile

    # ---------- Disconnect from WiFi ---------- # 
    def disconnect_from_wifi(self, profile):
        self.cmd('AT+UWSCA={},4'.format(profile)) # Deactivate profile

    # ---------- Erase a WiFi profile ---------- #
    def wifi_profile_erase(self, profile):
        self.wifi_disconnect(profile)
        self.cmd('AT+UWSCA={},0'.format(profile)) # Reset profile
        self.cmd('AT+UWSCA={},1'.format(profile)) # Store the blank profile

    def connect_to_domain(self, domain='example.com', port = 443, secure=True):
        self.HTTP = HTTP(domain, port, secure)
        self.cmd('AT+UDCP=tcp://{}:{}/{}'.format(domain,port,'?encr=1' if secure == True else ''))
        # self.cmd('AT+UDCP="tcp://{}:{}"'.format('192.0.2.1', 10000))

    def request_from_HTTP(self, subdirectory):
        request = self.HTTP.HTTP_GET_request_msg(subdirectory)
        print('\n'+request)
        self.send_text(request,self.channel_id)


class HTTP():
    def __init__(self, domain, port, secure=True):
        self.domain = domain
        self.port = port
        if secure == True:
            self.scheme = 'https'
            self.query_string = '?encr=1'
        else:
            self.scheme = 'http'
            self.query_string = ''
        
        self.data_received = ''

    def HTTP_GET_request_msg(self, subdirectory = '/api/activity'):
        msg = ('GET {}://{}:{}/{} HTTP/1.1\r\n'
        'Connection: Close\r\n'
        'Accept-Encoding: identity\r\n'
        'TE: identity\r\n'
        'Host: {}:{}\r\n\r\n').format(self.scheme, self.domain, self.port, subdirectory, self.domain, self.port)
        return msg
    
    def get_HTTP_msg(self):
        separated_data = self.data_received.split('\r\n')[-1][:-1]
        self.json_HTTP_request(separated_data)

    def json_HTTP_request(self, msg):
        import ujson
        msg_dict = ujson.loads(msg)
        print(msg_dict)


class MQTT_client(WiFi): # Broker/Server is HiveMQ
    def __new__(cls, *args, **kwargs):
        if Sys_Info.model == 'ODIN-W2' and int(Sys_Info.model_firmware[0]) < 7:
            raise FirmwareError("Update Network Component Firmware")
        else:
            return super().__new__(cls)
    
    def __init__(self, broker='your-broker.example.com', port=8883):
        super().__init__()
        self.broker = broker
        self.port = port
        self.MQTT_message = ''

    def show_message(self):
        print(self.MQTT_message)

    def subscribe_to_mqtt(self, client_id='', username = 'your_username', password = 'your_password', subscribe_topic = 'my/test/topic'):
        self.cmd('AT+UDCP=mqtt://{}:{}/?{}user={}&passwd={}&st={}&encr=1'.format(self.broker, self.port, client_id, username, password, subscribe_topic))

    def publish_to_mqtt(self, client_id='', username = 'your_username', password = 'your_password', publish_topic = 'my/test/topic', msg = 'Test Message'):
        self.cmd('AT+UDCP=mqtt://{}:{}/?{}user={}&passwd={}&pt={}&encr=1'.format(self.broker, self.port, client_id, username, password, publish_topic))
        print('WAITING...')
        vts.delay_ms(2000)
        self.send_publish_message(msg)

    def send_publish_message(self, msg):
        print('Sending Message: {}, {}'.format(msg,self.channel_id))
        self.send_text(msg,self.channel_id)

    # def ping(self):
    #     msg = ('PINGREQ: 0x0216'
    #     'Length: 0x02'
    #     'Type: 0x16 (PINGREQ)')
    #     self.send_text(msg,self.channel_id)

if __name__ == '__main__':
    # pass

    # Bluetooth Testing
    new_blue = Bluetooth()
    new_blue.set_bt_name('VBOX TouchV1')
    # new_blue.scan()

    # vts.delay_ms(15000)

    # new_blue.bond_to_device('OnePlus Nord CE 5G')

    # vts.delay_ms(15000)

    # new_blue.peer_connect('OnePlus Nord CE 5G')

    # WiFi Testing
    # new_wifi = WiFi()
    # profile = new_wifi.wifi_setup_connect('YourWiFiSSID', 'YourWiFiPassword')
    # new_wifi.connect_to_wifi(profile)

    # while new_wifi.connection_established == False:
    #     vts.delay_ms(1)

    # vts.delay_ms(10000)

    # domain = 'dns.google'
    # port = 443
    # new_wifi.connect_to_domain(domain, port = 443, secure = True)

    # vts.delay_ms(5000)

    # new_wifi.request_from_HTTP('resolve?name=dns.google&type=A')


    # MQTT Testing
    new_MQTT = MQTT_client()
    profile = new_MQTT.wifi_setup_connect('YourWiFiSSID', 'YourWiFiPassword')
    new_MQTT.connect_to_wifi(profile)

    while new_MQTT.fully_connected == False:
        vts.delay_ms(1)

    print("FULLY CONNECTED")

    new_MQTT.subscribe_to_mqtt()
    # vts.delay_ms(20000)
    # new_MQTT.cmd('AT+UDCPC=2')
    

    # new_MQTT.publish_to_mqtt(client_id='client=device:your-client-id&', username='your_username', password='your_password', publish_topic='topic/path')

    # new_MQTT.publish_to_mqtt()
    # vts.delay_ms(10000)
    # new_MQTT.cmd('AT+UDCPC=2')

    # print("Sending Ping to Channel ID: {}".format(new_MQTT.channel_id))
    # new_MQTT.ping()

    