// // main.cpp // BrainStem2-Client-Cpp-Example // // Created by Acroname Inc. on 5/20/2023. // Copyright (c) 2023 Acroname Inc. All rights reserved. // //This example is intended to highlight the multi-process and //network capabilities of BrainStem modules. This application //is intended to be used in conjunction with BrainStem2-Server-Cpp-Example //however, it will work with any application or even HubTool //if configured properly. //Note 1: // The actual server is created by the first process to connect to the device. // This means if you run this application first it would create/own // the server. This is intended to smooth over the user experience // but is important to remember when closing applications. If // The "Server" application is closed it will result in the "Clients" // losing access to the device. //Note 2: // This application was created with the aUSBHub3p object. If // your devices differs (say a USBCSwitch) you will need to change // all instances of aUSBHub3p to aUSBCSwitch in order to connect to // the device. This is a result of discoveryAndConnect as it will // only connect to a device that matches the object type. It is // possible to use the generic "Module" object; however, this was avoided // in order to present a simplified example. //Note 3: // If you intended to connect to a device that is not connected // to your local machine or on your local intranet (local network) // you will need to define a linkSpec with the intended ip and port // number of the device and then use "connectFromSpec". // Discovery works through broadcast and multicast packets; // neither of which work for the internet (global network). // For more connection types see the "Discovery-and-Connection" //Note 4: // Additional network details are described in _configure_aEther(). /////////////////////////////////////////////////////////////////////////////// // Includes /////////////////////////////////////////////////////////////////////////////// #include "BrainStem2/BrainStem-all.h" /////////////////////////////////////////////////////////////////////////////// // Private Macros /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // Private Types /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // Private Function Prototypes /////////////////////////////////////////////////////////////////////////////// void _configure_aEther(Acroname::BrainStem::Module& m); void _print_aEtherConfig(Acroname::BrainStem::Module& m); void _printProgramInfo(void); void _printFailedConnection(void); /////////////////////////////////////////////////////////////////////////////// // Public Data /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // Private Data /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // Public Function Implementations /////////////////////////////////////////////////////////////////////////////// int main(int argc, const char * argv[]) { aErr e = aErrNone; aUSBHub3p stem; //If your module is different, replace it with the appropriate module //Such as a USBCSwitch as shown below. //aUSBCSwitch stem; _configure_aEther(stem); e = stem.discoverAndConnect(USB); if(aErrNone == e) { _printProgramInfo(); printf("\n"); _print_aEtherConfig(stem); //Loop for a long time so that we can see the interactions //of the client and server. static const uint32_t NUM_LOOPS = 10000; for(uint32_t x = 0; x < NUM_LOOPS; x++) { if(x % 20 == 0) { printf("Loop: %d\n", x); } uint32_t voltage = 0; e = stem.system.getInputVoltage(&voltage); printf("System Input Voltage: %0.3f VDC - error: %d\n", double(voltage)/1000000, e); } stem.disconnect(); } else { _printFailedConnection(); } return 0; } /////////////////////////////////////////////////////////////////////////////// // Private Function Implementations /////////////////////////////////////////////////////////////////////////////// void _printProgramInfo(void) { printf("The aUSBHub3p client has been started.\n"); } void _configure_aEther(Acroname::BrainStem::Module& m) { //NOTE: Network configuration MUST be done before connecting. Acroname::BrainStem::aEtherConfig config; aErr err = m.getConfig(&config); if(err == aErrNone) { //Controls the exposure of the device. By default, //the device is only exposed on the localhost. //True = localhost(default); False = Public; //config.localOnly = false; //uncomment to test non-default values //Controls how strictly we honor the linkType (USB, NETWORK). //Fallback allows for a smoother user experience when getting //familiar with the device; however, it might be helpful to disable //this so that you can control who is the server and who is the client. //For instance if stem.discoverAndConnect(USB) fails it will automatically //try stem.discoverAndConnect(Network) and vise-versa. //True = fallback (default); False = NO fallback //config.fallback = false; //uncomment to test non-default values //Controls if the Client-Server model is used. If you prefer to restrict //the device to a single process you can disable this capability. //By default the stem is enabled for multi-process use. //True = Client-Server (default); False = Direct connection (not multi-process) //config.enabled = false; //uncomment to test non-default values //Allows the user to select what network interface the stem will be exposed to. //Default = LOCALHOST_IP_ADDRESS; (0 is also accepted for LOCALHOST_IP_ADDRESS); //Available interfaces can be found with aDiscovery_GetIPv4Interfaces //NOTE 1: // If config.localOnly == true; This value is ignored. // If config.localOnly == false; The stem will automatically pick // the highest priority network interface and will ignore 0 and // LOCALHOST_IP_ADDRESS values. However, you may override this value. //config.networkInterface = LOCALHOST_IP_ADDRESS; //Apply the configuration. aErr err = m.setConfig(config); if(err) { printf("setConfig Error: %d\n", err); } } } void _print_aEtherConfig(Acroname::BrainStem::Module& m) { Acroname::BrainStem::aEtherConfig config; aErr err = m.getConfig(&config); char sInterface[INET_ADDRSTRLEN]; aDiscovery_ConvertIPv4Interface(config.networkInterface, sInterface, INET_ADDRSTRLEN); printf("Current aEther Config (error: %d):\n", err); printf("\t Local Only: %d\n" \ "\t Fallback: %d\n" \ "\t Server Enabled: %d\n" \ "\t Assigned Port: %d\n" \ "\t Network Interface: %d (%s)\n", \ config.localOnly, config.fallback, config.enabled, config.assignedPort, config.networkInterface, sInterface); } void _printFailedConnection(void) { printf("Failed to discover Module\n"); printf(" - Confirm device is connected to your machine\n"); printf(" - Confirm object type. This examples default is \"aUSBHub3p\"\n"); }