===== TransSECS Devices - REST Client ===== The REST Client is an addon module for TransSECS. When you receive the module zip, save the file, but do not unzip it, but go to Help->Install Modules in TransSECS {{:pasted:20210929-131437.png}} then browse to the file. TransSECS will install the module. You then need to restart the TransSECS application. You need to be running the "TransSECSDevices" executable, not the main "TransSECS" application. {{:pasted:20210929-140552.png}} ===== Adding REST servers ===== Once the module is installed, you will be able to add a REST client. Add the "Devices" node, if it does not already exist by right-clicking on the root of the tree and selecting "Add Devices" {{:pasted:20210929-131800.png}} If the "UtilityServers node does not exist under the "Devices" node add that also: {{:pasted:20210929-131850.png}} After that you can add a REST Client: {{:pasted:20210929-131405.png}} Give your REST Client a suitable name. For reading ("GET") there's no need to configure the client: {{:pasted:20210929-132010.png}} When writing ("PUT" or "POST" ) you may need to set the "Content Type" under the expert properties tag: {{:pasted:20210929-132111.png}} Set this to "application/json" if you are going to send JSON to the server. ===== Calling REST Services ===== In this example, we perform two actions - request the recipe from a REST Service and use that in a PP-SELECT remote command and store data received at the end of a lot to a REST Service. ===== Populate the Recipe from a REST Services ===== When the "LotLoaded" report is received, we call a REST endpoint to get the correct recipe for the tool. This recipe is then set to the PP-SELECT remote command and that message is sent to the tool. The format of the URL we are calling is: http://hostname/Recipe/{toolname}/{lotid} an example, might be: http://localhost/Recipe/GEMHost/Lot123 Change this to match your service URL. In this case, the return is a JSON map. The script then parses the returned JSON and uses the recipe to populate the PP-SELECT remote host command. The REST call is on this line: resultJSON = /Devices/UtilityServers_Servers/GetRecipe->callRestServer("http://localhost:7000/Recipe/"+toolName+"/" + lotId, "GET", null); GetRecipe is the name of the REST server defined in the Devices/UtilityServers node: {{:pasted:20210929-133044.png}} callRestServer takes three arguments. The URL, the method ("GET", "PUT", etc.) and the data for the message. For "PUT", "POST" and similar methods, the data is placed in the body of the message. For "GET" methods (here) the data is ignored and can be null. // whenever this report is received, get the lotid, use the REST Service to read the recipe and then set it to the PP-SELECT S2F41 message and send it to the tool var TransSecsController = Java.type("com.ergotech.transsecs.secs.TransSecsController"); var DataSource = Java.type("com.ergotech.vib.servers.DataSource"); DataSource.logMessage ("Lot Loaded Event"); toolName = "GEMHost"; try{ host=TransSecsController.findController(toolName); lotId = incomingValue.getProperty("MAP").get("LOTID").getStringValue(); // the name must match exactly. It is case sensitive // demo URL http://hostname/Recipe/{toolname}/{lotid} resultJSON = /Devices/UtilityServers_Servers/GetRecipe->callRestServer("http://localhost:7000/Recipe/"+toolName+"/" + lotId, "GET", null); DataSource.logMessage ("LotId " + lotId + " Recipe JSON " + resultJSON); // in this case our JSON is just '{"Recipe":"recipe1"}' but could be any (valid) JSON resultMap = JSON.parse(resultJSON); ppid = resultMap.Recipe; //use this ppid and the lotid in the PPSELECT host command and send the message ppselect = host.getMessageBean("HostCommandPPSELECT"); ppselect.setCP2Value(lotId); // ser the LOTID ppselect.setCPValue(ppid); // set the PPID DataSource.logMessage ("Send the Message and wait for the reply"); reply=host.getMessageBean("HostCommandReply"); reply=ppselect.sendMessageAndWait(); // send the host command DataSource.logMessage ("Response "+ reply.getHCACK()[0]); if (reply.getHCACK()[0] == 0 ) { // could also be a 4 // good response print ("Recipe selection successful"); } else { print ("Recipe selection failed:" + reply.getHCACK()[0]); } } catch (e) { DataSource.logMessage("Error in LotLoaded Script: \n"+e.stack); print(e); } ===== Saving Data to a REST Services ===== When the "LotCompleted" report is received, we call a REST endpoint to save data. In this case, just the "wafercount" but any JSON (or any other string expected by the REST endpoint) can be sent. Similar to the recipe request, the, REST call is on this line: /Devices/UtilityServers_Servers/StoreData->callRestServer(url, "PUT", jsonString); StoreData is the name of the REST server defined in the Devices/UtilityServers node: {{:pasted:20210929-133044.png}} The first and second arguments to callRestServer are the url and the method, as with the "GET" request. The third argument is now the JSON string, the data that is placed in the body of the message. // whenever this report is received, get the lotid, use the REST Service to read the recipe and then set it to the PP-SELECT S2F41 message and send it to the tool var TransSecsController = Java.type("com.ergotech.transsecs.secs.TransSecsController"); toolName = "GEMHost"; print ("Lot Completed Event"); try{ host=TransSecsController.findController(toolName); waferCount = incomingValue.getProperty("MAP").get("WaferCount"); // the name must match exactly. It is case sensitive // demo URL http://hostname/StoreData/{toolname} // the body is a JSON-encoded string jsonString = '{"WaferCount":' + waferCount.getIntValue() +'}'; // any required values... url = "http://localhost:7000/StoreData/"+toolName; print ("Storing data \"" + jsonString + "\" to url \"" + url + "\""); /Devices/UtilityServers_Servers/StoreData->callRestServer(url, "PUT", jsonString); } catch (e) { print("Error in Lot Completed Script: \n"+e.stack); print(e); } ===== Testing ===== You can test the sample REST project with the StandAloneGEMTool application that is part of TransSECS, or with the TransSECS [[runningthegeneratedequipmentsimulator|Equipment Simulator]] created from your host project. For testing, you can use the [[https://github.com/jacopofar/demo-REST-server|Demo REST Server]] from Jacopo Farina on GitHub. Full documentation on how to run the demo is on the GitHub page. Possibly the simplest option is just to run the Docker image: docker run -p 7000:7000 --name restdemo jacopofar/demo-rest-server Using the "curl" application you can then add recipes. Here we add a recipe, "recipe1", for the lot id "Lot123": curl -X PUT -H "Content-Type: application/json" -d '{"Recipe":"recipe1"}' "http://localhost:7000/Recipe/GEMHost/Lot123" With the StandAloneGEMTool you can make the connection from your TransSECS host as normal. Build with the "hammer-and-star"{{:pasted:20210929-134003.png}} button then press the SIM/LIVE {{:pasted:20210929-134032.png}} to go LIVE. If you don't see the host connect to the tool, check your configuration and correct any mismatch and rebuild. {{:pasted:20210929-134337.png}} Once you're connected set the Lot ID field to "Lot123" to match the value in the REST server, then select the "LOADED" event and press the "Send Selected Event" message. {{:pasted:20210929-133901.png?400}} Select the "LOADED" event and press the "Send Selected Event" message. {{:pasted:20210929-135449.png?400}} You will see the event sent to the host, with the recipe "Lot123" and the PP-SELECT command sent from the host with the recipe and the lot id. Choose the "COMPLETED" event and send that event. You should see the event, and if you check the value in the REST server it should have the value of "1" curl -X GET -w "\n" -H "Content-Type: application/json" "http://localhost:7000/StoreData/GEMHost" (If you want to change the value in the REST server to be sure that it's actually chaning on the COMPLETED event, this command will set it to 22: curl -X PUT -H "Content-Type: application/json" -d '{"WaferCount":22}' http://localhost:7000/StoreData/GEMHost )