Get core ID over wifi?

I have no android or ios device and I got the core to connect using:

I cannot get the USB driver to work on vista 64. It complains about not being able to find the specified file.

Is there anyway to get the core ID via wifi?

1 Like

Hey @jfrisbie, great question.

First, check this thread for help resolving the “USB driver not found” issue: https://community.spark.io/t/usb-driver-not-found/673

Have you downloaded the Windows driver linked from the docs?
http://docs.spark.io/#/connect/connecting-your-core-connect-over-usb

It will be easier by far to use USB to get the ID, however, yes, in fact, if your Core is connecting to the Cloud, you can find out the ID over Wi-Fi!

When the Core finishes handshaking with the Spark Cloud, it multicasts a little presence announcement message on the local network. If you either just listen with wireshark or tcpdump, or else make a program that listens for the specific announcement, you could find it.

We’re using the CoAP standard, so the multicast address is 224.0.1.187, port 5683.
https://github.com/spark/core-firmware/blob/master/src/spark_utilities.cpp#L369

The message is 19 bytes long, a 7-byte header followed by the 12-byte ID:

I’ll follow up soon with a little script that would catch it on the local network.

I have the inf file however it complains about not being able to find the specified file after I browse for the inf. I will try the wireshark method you explained.

Thanks

Here’s a ruby listener for the presence announcement on the local network:

Try this INF file. When the Core is connected, select the location of the INF file at the prompt or via Device Manager and you should be done. Not sure whether copy/paste will work but trying to paste the contents. Save it something like “spark_core.INF”

; --------------------------------------------
; USB CDC ACM Setup File
; --------------------------------------------

[Version]
Signature="$Windows NT$"
Class=Ports
ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}
Provider=%PROVIDER%
LayoutFile=layout.inf
DriverVer=11/10/2009,5.2.0.0

[Manufacturer]
%DEVICE_DESCRIPTION%=DeviceList, NTx86, NTia64, NTamd64

[DeviceList.NTx86]
%DEVICE_DESCRIPTION%=DriverInstall, USB\VID_1D50&PID_607D

[DeviceList.NTia64]
%DEVICE_DESCRIPTION%=DriverInstall, USB\VID_1D50&PID_607D

[DeviceList.NTamd64]
%DEVICE_DESCRIPTION%=DriverInstall, USB\VID_1D50&PID_607D

[DriverCopyFiles]
usbser.sys,0x20
serenum.sys,0x20

;------------------------------------------------------------------------------
; Installation Configuration
;------------------------------------------------------------------------------

[DriverInstall]
include=mdmcpq.inf
CopyFiles=DriverCopyFiles
AddReg=DriverInstall.AddReg

[DriverInstall.HW]
AddReg=DriverInstall.HW.AddReg

[DriverInstall.AddReg]
HKR,EnumPropPages32,“MsPorts.dll,SerialPortPropPageProvider”

[DriverInstall.HW.AddReg]
HKR,NTMPDriver,*ntkern
HKR,NTMPDriver,usbser.sys
HKR,PortSubClass,1,01
HKR,“UpperFilters”,0x00010000,“serenum”

[DriverInstall.Services]
AddService=usbser, 0x00000002, UsbserService
AddService=Serenum,SerenumService

;------------------------------------------------------------------------------
; Usbser Service
;------------------------------------------------------------------------------

[UsbserService]
DisplayName=%USBSER.DESC%
ServiceType=1
StartType=3
ErrorControl=1
ServiceBinary=%12%\usbser.sys
LoadOrderGroup = Base

;------------------------------------------------------------------------------
; Serenum Service
;------------------------------------------------------------------------------

[SerenumService]
DisplayName = %SERENUM.DESC%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %12%\serenum.sys
LoadOrderGroup = PNP Filter

;------------------------------------------------------------------------------
; String Definitions
;------------------------------------------------------------------------------

[Strings]
PROVIDER="Spark Devices"
DEVICE_DESCRIPTION ="Spark Core with Wifi and Arduino Compatibility"
USBSER.DESC = "USB Serial Driver"
SERENUM.DESC = “Serenum Filter Driver”

Thanks but this driver throws the following error: “The filename, directory name, or volume label syntax is incorrect.”

Here’s a nodejs listener for the same!

var dgram = require("dgram");
var os = require('os');

var getIPAddresses = function () {
	var nics = os.networkInterfaces();

	var results = [];
	for (var name in nics) {
		if (!nics.hasOwnProperty(name)) { continue; }
		var nic = nics[name];

		for (var i = 0; i < nic.length; i++) {
			var addy = nic[i];
			if ((addy.family == "IPv4") 
                           && (addy.address != "127.0.0.1")) {
				results.push(addy.address);
			}
		}
	}
	return results;
};


var server = dgram.createSocket("udp4");
server.on("error", function (err) {
	console.log("server error:\n" + err.stack);
	server.close();
});
server.on("message", function (msg, rinfo) {
	var hex = msg.toString('hex');
	var idx = hex.indexOf('ff');
	var id = hex.substring(idx + 2);

	console.log("a core just announced itself! core id:" + id + " ip address: " + rinfo.address);
});
server.on("listening", function () {
	var address = server.address();
	console.log("server listening " + address.address + ":" + address.port);
});


var ips = getIPAddresses();
if (!ips || (ips.length == 0)) {
	console.error("error getting IP address!");
}
server.bind(5683, '0.0.0.0', function () {
	for(var i=0;i<ips.length;i++) {
		server.addMembership('224.0.1.187', ips[i]);
	}
});

Just wanted to drop some thanks for the nodejs code. It works awesome when a spark joins the network, but is there a way to look at the network to find any already there? I assume this is possible, but I’m not sure what the term would be called (so I can hit up Google).

The scenario is that my Spark is already running when I bring my node server online, but I have no clue what the IP is.

I was thinking that having node check the Spark API based on a device ID might also work (not even sure if there is a method for that)

1 Like

Hi @Endoplasmic

Thank you! Very glad that was useful for someone :smile:

One solution if you wanted to find your core on a local network would be to have your core announce itself regularly, instead of just when it connects to the cloud. All you would need to call in your firmware would be:

Multicast_Presence_Announcement();

You could also have that be triggered by an API request with something like:

Spark.function("announce", AnnounceMyself);

... <snip/> ...

int AnnounceMyself(String args) {
    Multicast_Presence_Announcement();  //advertise my ip locally
    return 0;
}

You could also have a similar UDP listener on the core, and have your node server send out a “who’s home” message locally that your cores could listen for, and then respond to.

Nice that works really well!

I think I’m going to use a combo of that method and something like this: https://community.spark.io/t/problems-using-core-as-client/2532/6 since the TCPServer just doesn’t work for beans on the core right now.

So what I’ll do is when the server starts it’ll call a Spark.function called “connect” which will tell the core the host and port (gotta find a quick tutorial on passing multiple args to a function) which creates the client connection to my node server. If the core hops offline and then back on again it’ll already call the multicast so I can then tell it to connect right after!

1 Like

Here is the code I’m using to tell the core to connect back to my server:

//args are ip,port (ie. xx.xx.xx.xx,1337)
int connectToServer(String args) {
    int index = args.indexOf(",");
    int count = 0;
    String digit = "";
    String ip = args.substring(0, index);
    
    for(unsigned int i = 0; i < ip.length(); i++) {
        if(ip.charAt(i) != '.'){
            digit += ip.charAt(i);
        }
        else {
            server_ip[count] = digit.toInt();
            count++;
            digit = "";
        }
    }
    
    //slap the last digit in there
    server_ip[count] = digit.toInt();

    port = args.substring(index + 1).toInt();
    
    client.connect(server_ip, port);
    return 0;
}
1 Like