<reponame>josiasMO/raspi_integrations
#!/usr/bin/env python
# *-* coding: utf-8 *-*

import subprocess
import threading
import socket
import os, sys
import time
from time import sleep
import logging
import ctypes
import binascii
import serial
from datetime import datetime

def crc16(datos, offset, length):
    crctab16 = (
        0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
        0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
        0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E,
        0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876,
        0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD,
        0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5,
        0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C,
        0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974,
        0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
        0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3,
        0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A,
        0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72,
        0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9,
        0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1,
        0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738,
        0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70,
        0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7,
        0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
        0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036,
        0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E,
        0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5,
        0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD,
        0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134,
        0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C,
        0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3,
        0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB,
        0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
        0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A,
        0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1,
        0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9,
        0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330,
        0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78,
    )
    fcs = 0xFFFF
    i = offset
    while i < length + offset:
        fcs = ((fcs >> 8) ^ crctab16[(fcs ^ datos[i]) & 0xFF])
        i += 1
    return ctypes.c_ushort(~fcs).value

def encoder(data):
    """encode sysjourney data
    0x20, 0x20, data_lenth, packet_id, data0, data1, ...., datan, check_h, check_l, 0x0D, 0x0A
    """
    strpackage = '2020' + '%002x' % len(data) + '19'
    for elem in data:
        strpackage = strpackage + '%002x' % int(elem)

    send_data = binascii.unhexlify(strpackage)


    chk_p = ' '.join(strpackage[i: i + 2] for i in range(0, len(strpackage), 2))
    chk_p = chk_p.split()
    chk_p = [int(p, 16) for p in chk_p]
    send_chk = crc16(chk_p[2:], 0, len(chk_p) - 2)

    send_chk = bytearray([(send_chk & 0xFF00) >> 8, send_chk & 0x00FF])
    return (send_data + send_chk + b"\r\n")

class GPRS(object):
    def __init__(self, host='rasp.dalmago.xyz', port=5555):
        self.proc = None
        self.host = host
        self.port = port

    def __ppp0status(self):
        """Check if the ppp0 connection is ready"""
        try:
            f = open('/sys/class/net/ppp0/operstate','r')
            if (f.readline() == 'unknown\n'):
                print('[PPPD]: ppp0 interface is UP')
                return 1
        except:
            return 0

    def __conn(self, data):
        """Open tcp socket and send data to the specified host"""
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.settimeout(10) #long timeout for gprs connections
        s.connect((self.host, self.port))
        s.sendall(data)
        recv = s.recv(1024)
        s.close()
        return recv

    def __procout(self, proc):
        """handle pppd subprocess output"""
        for line in iter(proc.stdout.readline, b''):
            print('[PPPD]: {0}'.format(line.decode('utf-8')), end='')

    def get_time(self):
        """
        Get time from gprs tracker, and clean the serial buffer
        return a list with the date and time
            [y_high, y_low, month, day, hour, minute, second ]
        """
        try:
            conn = serial.Serial("/dev/ttyS0", 115200, timeout=1)
            conn.flushInput()
            #get gprs time
            conn.write('AT+CCLK?'.encode('utf-8')+b'\r\n')
            conn.flush()
        except serial.SerialException:
            return ['0']*7

        received = conn.read(56).decode('utf-8').split('+CCLK: ')
        for line in received:
            if(line.startswith('"')):
                time = line[:19]
            else:
                time = None

        #clean buffer and close pyserial
        conn.flushInput()
        conn.flushOutput()
        conn.close()
        #check if the gprs tracker answered with the time
        try:
            if (len(time) > 1):
                #convert string to datetime
                time = datetime.strptime(time, '"%y/%m/%d,%H:%M:%S"')
                date_list = [time.year - 2000, \
                    time.month, time.day, time.hour, time.minute, time.second]
                return [str(a) for a in date_list]
            else: return ['0']*7
        except (IndexError,UnboundLocalError,TypeError): return ['0']*7


    def get_terminalID(self):
        """
            Request product serial number identification(IMEI)
            return a list with 8 integer numbers
        """
        try:
            conn = serial.Serial("/dev/ttyS0", 115200, timeout=1)
            conn.flushInput()
            conn.write('ATE1'.encode('utf-8')+b'\r\n')
            time.sleep(0.1)
            #get device imei
            conn.write('AT+CGSN'.encode('utf-8')+b'\r\n')
            conn.flush()

            received = conn.read(56).decode('utf-8').split('AT+')
            conn.write('ATE0'.encode('utf-8')+b'\r\n')

            conn.flushInput()
            conn.flushOutput()

        except serial.SerialException:
            print("Serial exeption during get imei")
            return ['0']*8
        #close serial connection
        conn.close()

        for line in received:
            if(line.startswith('CGSN')):
                received = line[10:25]
                received = '0'+received
            else:
                received = None
        if(received != None):
            received = [received[i:i+2] for i in range(0, len(received), 2)]
        else:
            return ['0']*8

        return received

    def send(self,data):
        """start pppd subprocess, handle the data form user"""
        proc = subprocess.Popen(['pppd','call','gprs'],
                                stdout=subprocess.PIPE,
                                stderr=subprocess.STDOUT)

        t = threading.Thread(target=self.__procout, args=(proc,))
        t.start()
        recv = None
        try:
            while proc.poll() is None:
                if(self.__ppp0status()):
                    r = encoder(data)
                    recv = self.__conn (r)
                    if recv is not None:
                        #the server should send back:
                        #     //0x00 = tudo ok
                        #     //0x08 = identicador não cadastrado
                        #     //0x09 = veículo ocupado por outro motorista
                        #     //0x0A = motorista não cadastrado
                        #     //0x0B = motorista em outro veículo
                        #     //0x0C = linha não cadastrada
                        #     //0x0D = veículo em outra linha
                        #     //0x0E = combinação veiculo x motorista já cadastrada
                        #     //0x0F = jornada não criada antes de finalizar
                        #    //0xFF = Erro desconhecido
                        if ord(recv) not in [250, 8 ,9, 10, 11, 12 ,13 , 14, 15 ,255]:
                            recv = None
                        proc.terminate()
                time.sleep(0.5)
        except socket.error as exc:
            proc.terminate()
            print ("socket.error : %s" % exc)
        finally:
            print('[PPPD]: End pppd process')
            try:
                proc.wait(timeout=2)
                print('== subprocess exited with rc =', proc.returncode)
            except subprocess.TimeoutExpired:
                print('subprocess did not terminate in time')
            t.join()
        print ('==Received from server %s bytes==' % recv)
        if recv is not None:
            return ord(recv)
        else:
            return None

# if __name__ == "__main__":
#     g = GPRS()
#     print (g.get_time())
#
#     # g.send(['0', '15','0', '35','0', '43', '0'] + g.get_time())
#     # time.sleep(2)

#!/usr/bin/env python
# *-* coding: utf-8 *-*

import subprocess
import threading
import socket
import os, sys
import time
from time import sleep
import logging
import ctypes
import binascii
import serial
from datetime import datetime

def crc16(datos, offset, length):
    crctab16 = (
        0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
        0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
        0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E,
        0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876,
        0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD,
        0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5,
        0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C,
        0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974,
        0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
        0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3,
        0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A,
        0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72,
        0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9,
        0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1,
        0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738,
        0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70,
        0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7,
        0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
        0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036,
        0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E,
        0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5,
        0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD,
        0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134,
        0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C,
        0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3,
        0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB,
        0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
        0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A,
        0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1,
        0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9,
        0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330,
        0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78,
    )
    fcs = 0xFFFF
    i = offset
    while i < length + offset:
        fcs = ((fcs >> 8) ^ crctab16[(fcs ^ datos[i]) & 0xFF])
        i += 1
    return ctypes.c_ushort(~fcs).value

def encoder(data):
    """encode sysjourney data
    0x20, 0x20, data_lenth, packet_id, data0, data1, ...., datan, check_h, check_l, 0x0D, 0x0A
    """
    strpackage = '2020' + '%002x' % len(data) + '19'
    for elem in data:
        strpackage = strpackage + '%002x' % int(elem)

    send_data = binascii.unhexlify(strpackage)


    chk_p = ' '.join(strpackage[i: i + 2] for i in range(0, len(strpackage), 2))
    chk_p = chk_p.split()
    chk_p = [int(p, 16) for p in chk_p]
    send_chk = crc16(chk_p[2:], 0, len(chk_p) - 2)

    send_chk = bytearray([(send_chk & 0xFF00) >> 8, send_chk & 0x00FF])
    return (send_data + send_chk + b"\r\n")

class GPRS(object):
    def __init__(self, host='rasp.dalmago.xyz', port=5555):
        self.proc = None
        self.host = host
        self.port = port

    def __ppp0status(self):
        """Check if the ppp0 connection is ready"""
        try:
            f = open('/sys/class/net/ppp0/operstate','r')
            if (f.readline() == 'unknown\n'):
                print('[PPPD]: ppp0 interface is UP')
                return 1
        except:
            return 0

    def __conn(self, data):
        """Open tcp socket and send data to the specified host"""
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.settimeout(10) #long timeout for gprs connections
        s.connect((self.host, self.port))
        s.sendall(data)
        recv = s.recv(1024)
        s.close()
        return recv

    def __procout(self, proc):
        """handle pppd subprocess output"""
        for line in iter(proc.stdout.readline, b''):
            print('[PPPD]: {0}'.format(line.decode('utf-8')), end='')

    def get_time(self):
        """
        Get time from gprs tracker, and clean the serial buffer
        return a list with the date and time
            [y_high, y_low, month, day, hour, minute, second ]
        """
        try:
            conn = serial.Serial("/dev/ttyS0", 115200, timeout=1)
            conn.flushInput()
            #get gprs time
            conn.write('AT+CCLK?'.encode('utf-8')+b'\r\n')
            conn.flush()
        except serial.SerialException:
            return ['0']*7

        received = conn.read(56).decode('utf-8').split('+CCLK: ')
        for line in received:
            if(line.startswith('"')):
                time = line[:19]
            else:
                time = None

        #clean buffer and close pyserial
        conn.flushInput()
        conn.flushOutput()
        conn.close()
        #check if the gprs tracker answered with the time
        try:
            if (len(time) > 1):
                #convert string to datetime
                time = datetime.strptime(time, '"%y/%m/%d,%H:%M:%S"')
                date_list = [time.year - 2000, \
                    time.month, time.day, time.hour, time.minute, time.second]
                return [str(a) for a in date_list]
            else: return ['0']*7
        except (IndexError,UnboundLocalError,TypeError): return ['0']*7


    def get_terminalID(self):
        """
            Request product serial number identification(IMEI)
            return a list with 8 integer numbers
        """
        try:
            conn = serial.Serial("/dev/ttyS0", 115200, timeout=1)
            conn.flushInput()
            conn.write('ATE1'.encode('utf-8')+b'\r\n')
            time.sleep(0.1)
            #get device imei
            conn.write('AT+CGSN'.encode('utf-8')+b'\r\n')
            conn.flush()

            received = conn.read(56).decode('utf-8').split('AT+')
            conn.write('ATE0'.encode('utf-8')+b'\r\n')

            conn.flushInput()
            conn.flushOutput()

        except serial.SerialException:
            print("Serial exeption during get imei")
            return ['0']*8
        #close serial connection
        conn.close()

        for line in received:
            if(line.startswith('CGSN')):
                received = line[10:25]
                received = '0'+received
            else:
                received = None
        if(received != None):
            received = [received[i:i+2] for i in range(0, len(received), 2)]
        else:
            return ['0']*8

        return received

    def send(self,data):
        """start pppd subprocess, handle the data form user"""
        proc = subprocess.Popen(['pppd','call','gprs'],
                                stdout=subprocess.PIPE,
                                stderr=subprocess.STDOUT)

        t = threading.Thread(target=self.__procout, args=(proc,))
        t.start()
        recv = None
        try:
            while proc.poll() is None:
                if(self.__ppp0status()):
                    r = encoder(data)
                    recv = self.__conn (r)
                    if recv is not None:
                        #the server should send back:
                        #     //0x00 = tudo ok
                        #     //0x08 = identicador não cadastrado
                        #     //0x09 = veículo ocupado por outro motorista
                        #     //0x0A = motorista não cadastrado
                        #     //0x0B = motorista em outro veículo
                        #     //0x0C = linha não cadastrada
                        #     //0x0D = veículo em outra linha
                        #     //0x0E = combinação veiculo x motorista já cadastrada
                        #     //0x0F = jornada não criada antes de finalizar
                        #    //0xFF = Erro desconhecido
                        if ord(recv) not in [250, 8 ,9, 10, 11, 12 ,13 , 14, 15 ,255]:
                            recv = None
                        proc.terminate()
                time.sleep(0.5)
        except socket.error as exc:
            proc.terminate()
            print ("socket.error : %s" % exc)
        finally:
            print('[PPPD]: End pppd process')
            try:
                proc.wait(timeout=2)
                print('== subprocess exited with rc =', proc.returncode)
            except subprocess.TimeoutExpired:
                print('subprocess did not terminate in time')
            t.join()
        print ('==Received from server %s bytes==' % recv)
        if recv is not None:
            return ord(recv)
        else:
            return None

# if __name__ == "__main__":
#     g = GPRS()
#     print (g.get_time())
#
#     # g.send(['0', '15','0', '35','0', '43', '0'] + g.get_time())
#     # time.sleep(2)
#!/usr/bin/env python # *-* coding: utf-8 *-* encode sysjourney data     0x20, 0x20, data_lenth, packet_id, data0, data1, ...., datan, check_h, check_l, 0x0D, 0x0A Check if the ppp0 connection is ready Open tcp socket and send data to the specified host #long timeout for gprs connections handle pppd subprocess output Get time from gprs tracker, and clean the serial buffer         return a list with the date and time             [y_high, y_low, month, day, hour, minute, second ] #get gprs time #clean buffer and close pyserial #check if the gprs tracker answered with the time #convert string to datetime Request product serial number identification(IMEI)             return a list with 8 integer numbers #get device imei #close serial connection start pppd subprocess, handle the data form user #the server should send back: #     //0x00 = tudo ok #     //0x08 = identicador não cadastrado #     //0x09 = veículo ocupado por outro motorista #     //0x0A = motorista não cadastrado #     //0x0B = motorista em outro veículo #     //0x0C = linha não cadastrada #     //0x0D = veículo em outra linha #     //0x0E = combinação veiculo x motorista já cadastrada #     //0x0F = jornada não criada antes de finalizar #    //0xFF = Erro desconhecido # if __name__ == "__main__": #     g = GPRS() #     print (g.get_time()) # #     # g.send(['0', '15','0', '35','0', '43', '0'] + g.get_time()) #     # time.sleep(2)