#!/usr/bin/python

# $Header: https://oberon.oapd.inaf.it/shins/trunk/shins/test/end_2_end/telnet_motion.py 353 2017-12-14 11:06:33Z depa $

import telnet_connection as tc
import telnetlib
import timer
import signal
import sys

def test_motion(modules):
    print "\nBEGIN TEST\n"

    # We have three MoCon boards: 3 hosts

    host0 = "192.168.1.51" # test MoCon in office
    host1 = "192.168.103.50" # MoCon1 Stepper motors 2 ADC 1 rotator 
    host2 = "192.168.103.51" # MoCon2 DC motors
    host3 = "192.168.103.52" # MoCon3 DC motors

    # port is always the same
    port = 4000

    CONST_CARD_N = 1

    timeout = 3 # seconds
    steps = -1000

    print "\n> Opening telnet connection to host {} on port {}".format(host0, port)
    T = timer.timer()

    T.begin()
    tn = tc.connect(host0, port, timeout)
    if T.elapsed() >= timeout:
        raise RuntimeWarning("Connection to {} timeout!".format(host0))
    cr = "\r\n"

    user = "user"
    passwd = "mpia"

    tcpLogin = b"{} 21 0 {}".format(CONST_CARD_N, user) + cr
    tcpPasswd = b"{} 22 0 {}".format(CONST_CARD_N, passwd) + cr
    tcpLogout = b"{} 29 0".format(CONST_CARD_N) + cr

    errCode =[
        -10, # see page 114, 115
        -18, # Module already reserved
        -19 # Module not reserved
    ]

    expectedOuput = []


    #defining signal handler to catch CTRL+c to avoid not closing telnet connection
    def signal_handler(signal, frame):
        print('You pressed Ctrl+C!')
        tn.write(tcpLogout)
        tn.close()
        raise KeyboardInterrupt

    #registering handler with signal.signal
    signal.signal(signal.SIGINT, signal_handler)

    ack = b"System ready..."

    expectedOuput.append(ack)

    T.begin()
    output = tn.expect(expectedOuput, timeout)
    if T.elapsed() >= timeout:
        raise RuntimeWarning("Timeout after connection to {}".format(host0))
    print output[2]
    # print tn.read_until(ack, timeout)

    print "\n> Logging in as: {}".format(user)
    tn.write(tcpLogin)
    ack = b"{} 21 0 1".format(CONST_CARD_N)
    T.begin()
    print tn.read_until(ack, timeout)
    if (T.elapsed() >= timeout):
        raise RuntimeWarning("Login to {} timeout".format(host0))

    print "\n> with passwd: {}".format(passwd)
    tn.write(tcpPasswd)
    ack = b"{} 22 0 1".format(CONST_CARD_N)
    T.begin()
    print tn.read_until(ack, timeout)
    if (T.elapsed() >= timeout):
        raise RuntimeWarning("Login to {} timeout".format(host0))

    print b"> CardNo {} TEST".format(CONST_CARD_N)

    for moduleN in modules:
        # 1. Reseve the module
        # moduleN = 1 # we can iterate on this
        reserveModule = b"{} 23 {}".format(CONST_CARD_N, moduleN) + cr
        for e in errCode:
            err = "{} 23 {} {}".format(CONST_CARD_N, moduleN, e)
            expectedOuput.append(err)

        ack = b"{} 23 {} 1".format(CONST_CARD_N, moduleN)
        expectedOuput.append(ack)
        print "\n> Reserving module No {}".format(moduleN)
        tn.write(reserveModule)
        if "-18" in reserveModule:
            print "\n> ERROR Module already reserved!"
        T.begin()
        output = tn.expect(expectedOuput, timeout)
        if (T.elapsed() >= timeout):
            raise RuntimeWarning("Reserving module {} at {} timeout".format(moduleN, host0))

        print output[2]

        # 2. Move absolute steps
        moveAbsSteps = b"{} 123 {} {}".format(CONST_CARD_N, moduleN, steps) + cr
        for e in errCode:
            err = "{} 123 {} {}".format(CONST_CARD_N, moduleN, e)
            expectedOuput.append(err)

        ack = b"{} 123 {} 1".format(CONST_CARD_N, moduleN)
        expectedOuput.append(ack)
        print "\n> Moving module No {} by {} steps (REL)".format(moduleN, steps)
        tn.write(moveAbsSteps)
        T.begin()
        output = tn.expect(expectedOuput, timeout)
        if (T.elapsed() >= timeout):
            raise RuntimeWarning("Commanding module {} at {} timeout".format(moduleN, host0))
        print output[2]



        # 3. Free the module
        freeModule = "{} 24 {}".format(CONST_CARD_N, moduleN) + cr
        ack = "{} 24 {} 1".format(CONST_CARD_N, moduleN)
        expectedOuput.append(ack)
        print "\n> Free module No {}".format(moduleN)
        tn.write(freeModule)
        T.begin()
        output = tn.expect(expectedOuput, timeout)
        if (T.elapsed() >= timeout):
            raise RuntimeWarning("Freeing module {} at {} timeout".format(moduleN, host0))

        print output[2]



    print "> Logout\n"
    tn.write(tcpLogout)
    print "> Closing connection\n"
    tn.close()

    print "\nEND TEST\n"

if __name__ == "__main__":
    test_motion()
