Local spark core - TCP? Server or Client?

Hi all,

I want to make a local use Spark implementation, I already have a version working that uses the cloud, but the area has intermittent internet access, so I want to cut out the cloud side of things.

I think I’ll make a server/client type of relationship, but am unsure how I should do it. Should I make the core a server, or make the core a client, with a server app on a mobile phone? I just want to have the two components, not to have a third gadget doing the serving. The environment where I’ll deploy already has a WIFI network in place.

I’ve never successfully made a server and client, so will have to start really basic. I haven’t been able to find a server example that I could make work yet.

The data to be transmitted is low volume. I want to have confirmation of connection, an on/off state sent, and a speed signal sent. The on off needs to be pretty realtime, within a second or so, and when active, it will then send the speed info, for about 4 minutes or so.

Thanks
Jim

1 Like

Hey Jim,

Have you looked into running you own Local Cloud? In my opinion the cloud aspects of the core are the coolest aspects of the SparkCore and it would be a shame to go without them if you don’t have to.

1 Like

I haven’t, as I am trying to keep the complexity down as much as possible. I could give it a try, but would like to make this concept work with minimum components…

I completely understand. I think the major “investment” when going the local cloud route would be the time investment. If you don’t mind “doing the time” then drop $50 for a Pi set (Pi + Power Supply + SD Card) and go the local cloud route.

If you want to just use the cores can I get a better description of your setup? Thanks!

Hi Jim,

It sounds like the most simple solution if you’re wanting to quickly move data around locally would be to use the manual or semi-automatic modes on the core. That way you can still flash firmware OTA to the core, and check on it, but you can disable it when not in use (with a jumper or otherwise). You can use TCPServer/TCPClient, or UDP to push packets around on your local network. I would recommend UDP if you’re not as worried about ordering / reliability, and you just want speed / broadcast instead.

If you use TCPServer/TCPClient, you just need to have / know addresses for things ahead of time, or have a way to pass them in. This is where a UDP broadcast can be nicer, since anyone on the network can just listen to a broadcast address. I hope that helps! :slight_smile:

Thanks,
David

OK,
Well, I’ll hedge my bets and get a Pi as well as heading down the UDP road.

RE: UDP
I’ve got the local echo server working, but want to tweak it for my uses. How can I broadcast udp without knowing the destination address? To broadcast it to anything listening on that port?

I was also going to try to broadcast UDP to a specific address, but don’t quite get how to put an IP address into a variable… It tells me I have too many decimal places, I guess I need to know how to put in a 4 byte variable…??

Thx.

Ok, so I have some udp working with my code, but currently I have to have a specific up address to send it to. I’ve tried to use 255.255.255.255 and 192.168.5.255, but I only receive the packets when I specify the exact IP address. Any suggestions??

Hi @jimbol

Post some code and we can help you debug it.

OK, here’s the code. I’m trying to get the UDP to go to all addresses on network, so I don’t have to figure out what addresses need to receive it.

Not sure how to format this to put all my code in a code window… Sorry.

TCPClient myTCP;

int sentOnce = 0;
unsigned long TimeSinceChange = 5;
unsigned long TimeSinceNotification = 11;
unsigned long TimeOfChange = 0;
unsigned long TimeOfNotification = 0;
void interruptCode();
void checkTimes();
// UDP Port used for two way communication
unsigned int localPort = 8888;
// An UDP instance to let us send and receive packets over UDP
UDP Udp;

void setup() {
    pinMode(D1, INPUT_PULLDOWN);
    attachInterrupt(D1, interruptCode, CHANGE);
    Serial.begin(9600);
        // Initialise UDP
    Udp.begin(localPort);
}
 
void loop() 
{
    checkTimes();
    Udp.flush();
    
    Serial.print("tsn...");
    Serial.print(TimeSinceNotification);
    Serial.print("   tsc...");
    Serial.print(TimeSinceChange);
    Serial.print("   SentOnce...");
    Serial.println(sentOnce);
        
        if (TimeSinceChange < 2) 
        {
            Serial.println("here we go...");
            RGB.control(true);
            RGB.color(250,0,0);
            if (sentOnce == 0) 
            {
                sendGetRequest();
            }
            RGB.control(false);
        }
}

void sendGetRequest()
{
   if (myTCP.connect("api.prowlapp.com", 80))
        {
        Serial.println(F("Outgoing Notification"));
        myTCP.write("POST https://api.prowlapp.com/publicapi/add?apikey=API KEY HERE);
        myTCP.stop();
        }
        TimeOfNotification = (millis()/1000);
        sentOnce = 1;
          // Store sender ip and port
        IPAddress ipAddress (192, 168, 5, 61);
        int port = Udp.remotePort();
        
   
        Udp.beginPacket(ipAddress,8888);
        Udp.write("Fish");
        Serial.println("Fish");
        Udp.endPacket();
}
void interruptCode()
    {
        TimeOfChange = (millis()/1000);
        Serial.println("Interrupt occurred.");
    }

void checkTimes()
    {
        TimeSinceChange = ((millis()/1000) - TimeOfChange);
        TimeSinceNotification = ((millis()/1000) - TimeOfNotification);
        if (TimeSinceChange > 15) {sentOnce = 0;}
    }

Thx BKO,
The code is in the post above. It works with the specific address in it, but not with a broadcast address - 192.168.5.255 or 255.255.255.255
It would be very helpful for me to get to the point where I don’t have to assign the exact address, as I want the system to be mobile between different networks.
Jim

OK, a couple things jump out at me.

  • You are using the same port for talk and listen, so in the broadcast case, you will receive your own packets. You need to read them or you will run out of packet buffers in the TI WiFi chip and your core will slow down or reset.

  • I can broadcast UDP packets on 255.255.255.255 on my network, but not every router supports this.

  • You can use the WiFi.localIP() to get the address of the network you are on and construct a subnet broadcast address from that like this:

//In loop or setup so that WiFi is already up and running
IPAddress myIP = WiFi.localIP;
IPAddress bcastIP(myIP[1],myIP[2],myIP[3],255);

Well, I’ve been doing that, but with no luck.
I also put in the Udp.flush(); to hopefully take care of a full buffer…

but now I think this is a different problem, as I just tried this with an app on my iPhone and another on my mac, and I can’t get the packets when I try to send to a subnet broadcast.

This could well be an issue with my network not allowing the broadcasts…

thx

Have you considered using Voodoospark? It’s a custom firmware that exposes the Spark API via TCP:
http://voodoospark.me/

//In loop or setup so that WiFi is already up and running
IPAddress myIP = WiFi.localIP;
IPAddress bcastIP(myIP[0],myIP[1],myIP[2],255);

I got this wrong–sorry. Start at zero not one. This works for me.

@bko
It seems like I have an issue within my local network environment that is preventing the broadcasts from reaching destinations. I’m in a tricky network, that I really don’t understand all the complexities of.

It’s probably in my router, which manages several VLANs, and routes them to one of several methods different WANs, depending on what is available - VSAT, GSM, shore ethernet, or Wifi. There is a managed switch or two also in the mix, which could be the culprit, and then a system of 5 or 6 cisco AP’s that spread the wifi networks thru the ship. There’s a huge difference between latency on the different types of internet access, and when using cloud stuff something that works over GSM 3g or 4g doesn’t necessarily work over vsat or wifi… Yikes.

This is my reason for wanting to cut the cloud out of the loop entirely, and do everything locally, but one of the bigger problems is that push notifications are only accessible via APNS, and I want to figure a way to get a push thru to a sleeping phone, when there is not any access beyond the LAN.

I think I’ll drop the UDP broadcasts, and use an assigned IP address so I can move on and not get too frustrated.

@harrisonhjones I’m working on getting a Pi server up and running, indeed I think I have that now, but haven’t figured out how to use it!

The UDP broadcast I was trying to do was to send data to an iPhone. The whole thing I’m trying to do is to send a notification to an iPhone, then afterwards to have that iPhone talk to the core, to get some info on speed of a sensor.

So if anyone has an idea on how to get a push to an iPhone without a cloud component, then I’m all ears!!!

Otherwise, I’d like to get some of the functionality going via the local cloud, but I’m not really sure of my next steps to do that! Yet…

1 Like

Hi @jimbol

I think for APNS you will need a server on the same subnet as your core and phone. This could be tricky in your network setup.

One other idea I had for you was to use email. I can send email from a core to my local ISP email since I am “inside” their firewall without using HTTPS. Then I can get a normal iPhone email notification. @Dave posted some SMTP code quite a while back:

1 Like