import os
import sys
import string
import base64
import httplib
import time

#configurables
IDIGI_ADDR    = "app.idigi.com"         #hostname of iDigi Server to Connect to
USERNAME      = "tkim"                  #username on that account
PASSWORD      = "password"              #password on that account
IP_LIST       = "iplist.txt"            #List of devices to upgrade
GENOUTPUT_CSV = "gen_output.csv"        #CSV file of what was actually done
WAIT_TIME     = 1800

#non-configurables
DEV_REQUEST_DEVCORE = "/ws/DeviceCore"        #device list request
DEV_REQUEST_SCI = "/ws/sci"
sci_header = "<sci_request version=\"1.0\"><send_message><targets><device id=\""
sci_header_refresh = "<sci_request version=\"1.0\"><send_message cache=\"false\"><targets><device id=\""
sci_end_targets = "\"/></targets>"
sci_tail = "</send_message></sci_request>"
rci_get_mtu_x4 = "<rci_request version=\"1.1\"><query_setting><mobileppp/></query_setting></rci_request>"
rci_get_mtu_wan = "<rci_request version=\"1.1\"><query_setting><ppp index=\"130\"/></query_setting></rci_request>"
rci_update_mtu_x4 = "<rci_request version=\"1.1\"><set_setting><mobileppp><mru>1400</mru><mtu>1400</mtu></mobileppp></set_setting></rci_request>"
rci_update_mtu_wan = "<rci_request version=\"1.1\"><set_setting><ppp index=\"130\"><mru>1400</mru><mtu>1400</mtu></ppp></set_setting></rci_request>"
rci_reboot = "<rci_request version=\"1.1\"><reboot/></rci_request>"
rci_get_fw_ver = "<rci_request version=\"1.1\"><query_state><device_info/></query_state></rci_request>"
rci_generic_query = "<rci_request version=\"1.1\"><query_setting/></rci_request>" 

sci_update_header = "<sci_request version=\"1.0\"><update_firmware><targets><device id=\""
sci_update_end_targets = "\"/></targets><data>"
sci_update_tail = "</data></update_firmware></sci_request>"

DEV_STATE_DISCONNECTED      = "Disconnected"
DEV_STATE_UPDATED           = "Updated"
DEV_STATE_NOT_UPDATED       = "Not Updated"
DEV_STATE_FAILED_UPDATE     = "Failed Update"
PYTHON_DIR                  = "/WEB/python"
NO_DEV_FOUND                = "No Device Found"
DEV_UPDATE_SUCCESS          = "Success"


class device_class:
    #regular stats
    devConnectwareId = ""
    dpDeviceType = ""
    dpContact = ""
    dpFirmwareLevelDesc = ""
    dpLastConnectTime = ""
    dpLastKnownIp = ""
    dpConnectionStatus = ""    
    error_msg = ""
    #extended stats
    mtu_size = ""
    mru_size = ""


def checkStatus():
    print "Establishing connection to iDigi and requesting Device list"

    connection = httplib.HTTPConnection(IDIGI_ADDR)
    connection.putrequest("GET", DEV_REQUEST_DEVCORE)
    connection.putheader("Authorization", "Basic " + auth)
    connection.endheaders()
    connection.send("")
    response = connection.getresponse()
    data = response.read()
    
    currentdevices = 0
    remainingDevices = 1
    devlist = []
    connected_count = 0
    disconnected_count = 0
        
    while remainingDevices > 0:
        retA = data.find("<resultSize>")
        if retA < 0:
            print "[[Error]] " + data
            return [], 0, 0        

        retB = data.find("</resultSize>")
        resultSize = int(data[retA + 12:retB])
        currentdevices = currentdevices + resultSize
        
        retA = data.find("<remainingSize>")
        if retA > 0:
            retB = data.find("</remainingSize>")
            remainingDevices = int(data[retA + 15:retB])
        else:
            remainingDevices = 0

        print "Recieved " + str(resultSize) + " devices, " + str(remainingDevices) +" remaining"
    
        count = 0
        
        while count < resultSize:
            count = count + 1
            
            tempdevice = device_class()
            tempdevice.devConnectwareId = "Unknown Device ID"
            tempdevice.dpDeviceType = "Unknown Device Type"
            tempdevice.dpContact = "Unknown Contact"
            tempdevice.dpFirmwareLevelDesc = "Unknown Firmware"
            tempdevice.dpLastConnectTime = "Unknown Connect Time"
            tempdevice.dpLastKnownIp = "Unknown IP"
            tempdevice.dpConnectionStatus = "Unknown Connection Status"
            tempdevice.error_msg = ""
            #extended values set to default, found later
            tempdevice.mtu_size = "Unknown MTU Size"
            tempdevice.mru_size = "Unknown MRU Size"

            next_msg = data.find("</DeviceCore>")

            retA = data.find("<devConnectwareId>")
            if (retA > 0) and (retA < next_msg):
                retB = data.find("</devConnectwareId>")
                tempdevice.devConnectwareId = data[retA + 18:retB]

            retA = data.find("<dpDeviceType>")
            if (retA > 0) and (retA < next_msg):
                retB = data.find("</dpDeviceType>")
                tempdevice.dpDeviceType = data[retA + 14:retB]                

            retA = data.find("<dpContact>")
            if (retA > 0) and (retA < next_msg):
                retB = data.find("</dpContact>")
                tempdevice.dpContact = data[retA + 11:retB]

            retA = data.find("<dpFirmwareLevelDesc>")
            if (retA > 0) and (retA < next_msg):
                retB = data.find("</dpFirmwareLevelDesc>")
                tempdevice.dpFirmwareLevelDesc = data[retA + 21:retB]
  
            retA = data.find("<dpLastConnectTime>")
            if (retA > 0) and (retA < next_msg):
                retB = data.find("</dpLastConnectTime>")
                dpLastConnectTimeUTC = data[retA + 19:retB]
                tempdevice.dpLastConnectTime = dpLastConnectTimeUTC[11:19] + " " + dpLastConnectTimeUTC[5:7] + "-" + dpLastConnectTimeUTC[8:10] + "-" + dpLastConnectTimeUTC[:4]
            else:
                tempdevice.dpLastConnectTime = "Never Connected    "
        
            retA = data.find("<dpLastKnownIp>")
            if (retA > 0) and (retA < next_msg):
                retB = data.find("</dpLastKnownIp>")
                tempdevice.dpLastKnownIp = data[retA + 15:retB]
            
            retA = data.find("<dpConnectionStatus>")
            if (retA > 0) and (retA < next_msg):
                retB = data.find("</dpConnectionStatus>")
                dpConnectionStatusNum = data[retA + 20:retB]
        
                if dpConnectionStatusNum == "1":
                    tempdevice.dpConnectionStatus = "Connected"
                    connected_count = connected_count + 1 
                else:
                    tempdevice.dpConnectionStatus = DEV_STATE_DISCONNECTED
                    disconnected_count = disconnected_count + 1

            devlist.append(tempdevice)
            
            data = data[next_msg + 13:]

        if remainingDevices > 0:
            print "Sending another request for devices"
            connection.putrequest("GET", DEV_REQUEST_DEVCORE + "?start=" + str(currentdevices) + "&size=1000")
            connection.putheader("Authorization", "Basic " + auth)
            connection.endheaders()
            connection.send("")
            response = connection.getresponse()
            data = response.read()

    connection.close()
         
    return devlist, connected_count, disconnected_count


def parse_xml(string, substring):
    output = ""
    retA = string.find("<" + substring + ">")
    if retA > 0:
        retB = string.find("</" + substring + ">")
        output = string[retA + len(substring) + 2:retB]
    
    return output    

#main
auth = base64.b64encode("%s:%s" % (USERNAME, PASSWORD))

print "[" + time.strftime('%X %x %Z') + "] Starting Grabbing devices"
devlist, connected_count, disconnected_count = checkStatus()
print "[" + time.strftime('%X %x %Z') + "] Finished Grabbing devices"

fd = open("iplist.txt", 'r')
data = fd.read()
iplist = data.split('\n')
fd.close()

count = 0

fh = open(GENOUTPUT_CSV, "w")
    
for ip in iplist:
    if ip == "":
        continue
    
    count = count + 1
    
    print "[" + str(count) + "] Working on: " + ip
    
    for x in range(len(devlist)):
        if ip == devlist[x].dpLastKnownIp:
            line = devlist[x].devConnectwareId + "," + devlist[x].dpLastKnownIp + "," + \
                   devlist[x].dpLastConnectTime + "," + devlist[x].dpConnectionStatus + "," + \
                   devlist[x].dpContact + "," + devlist[x].dpDeviceType + "," + \
                   devlist[x].dpFirmwareLevelDesc + "\n"
            fh.write(line)

fh.close()
    
print "[" + time.strftime('%X %x %Z') + "] Complete"
