Search code examples
perlsocketsswift-playgroundhome-automation

How to implement a socket connection using a swift playground?


I have this simple Perl software to monitor the activity of a my home automation bus and "say" when a light changes its status. I would like to implemented it using the Swift language using the Xcode playground. Any solutions to try?

#!/usr/bin/perl -w
#
use strict;
use IO::Socket::INET;
my $mh200ip = "10.0.1.82";
my $ownport = "20000";
my $frames;
my $socket = IO::Socket::INET->new(
    PeerAddr => $mh200ip,
    PeerPort => $ownport,
    Proto    => "tcp",
    Type     => SOCK_STREAM
);
die "Could not create socket: $!\n" unless $socket;
$socket->send("*99*1##");    # Sending OPEN ACK

while (1) {
    $socket->recv( $frames, 128 );
    if ( $frames ne '' ) {
        print "$frames\n";
        my $data = ($frames);
        my @values = split( '##', $data );
        if ( $data eq "*1*0*53##" ) {
            `say "light off"`;
        }
        if ( $data eq "*1*1*53##" ) {
            `say "light on"`;
        }
    } else {
        print "server closed connection";
        exit 1;
    }
}

Solution

  • This is an almost-verbatim translation into Swift of your Perl snippet:

    #!/usr/bin/swift
    import Foundation
    
    func say(whatToSay: String) {
        let task = NSTask()
        task.launchPath = "/usr/bin/say"
        task.arguments = [whatToSay]
        task.launch()
    }
    
    let addr = "127.0.0.1"
    let port = 2000
    
    var buffer = [UInt8](count: 255, repeatedValue: 0)
    
    var inp : NSInputStream?
    var out : NSOutputStream?
    
    NSStream.getStreamsToHostWithName(addr, port: port, inputStream: &inp, outputStream: &out)
    
    if inp != nil && out != nil {
        let inputStream : NSInputStream = inp!
        let outputStream : NSOutputStream = out!
        inputStream.open()
        outputStream.open()
    
        if outputStream.streamError == nil && inputStream.streamError == nil {
            let queryString: String = "*99*1##"
            let queryData: NSData = queryString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
            while true {
                outputStream.write(UnsafePointer(queryData.bytes),maxLength:queryData.length)
                var readChars: Int = inputStream.read(&buffer, maxLength: buffer.count)
                if (readChars > 0) {
                    let readString: String = NSString(data: NSData(bytes:buffer, length:readChars), encoding: NSUTF8StringEncoding)!
                    if readString == "*1*0*53##" {
                        say("Light off")
                    } else if readString == "*1*1*53##" {
                        say("Light on")
                    }
                } else {
                    println ("server closed connection")
                    inputStream.close()
                    outputStream.close()
                    break
                }
            }
        } else {
            println ("could not create socket")
        }
    } else {
        println ("could not initialize stream")
    }