I'm working on a student project and trying to send JSON data (based on the twitter hashtag '#tune') from Processing to Arduino, but the method 'myPort.write(status);' isn't usable with JSON, I've looked around online but not sure what command to use - Am I on the right track? Here's the code:
Processing:
import processing.serial.*; //Serial connection for Arduino
import java.lang.reflect.Method;
import com.temboo.core.*; // Temboo library
import com.temboo.Library.Twitter.Search.*; // Temboo Twitter search library
// Create a session using your Temboo account application details
TembooSession session = new TembooSession("MYUSERNAME", "MYTEMBOOAPPNAME", "MYTEMBOOCODE");
// Setup objects
Serial myPort; // Create object from Serial class
int portNo = 7; // Define portNo as int
int baudRate = 9600; // Define baudRate as int
void setup() {
// Run the Tweets Choreo function
runTweetsChoreo();
String portName = Serial.list()[portNo]; // Setup String for port ([7] is the port number for my machine)
myPort = new Serial(this, portName, baudRate); // Setting up serial port
}
void runTweetsChoreo() {
// Create the Choreo object using your Temboo session
Tweets tweetsChoreo = new Tweets(session);
// Set credential
tweetsChoreo.setCredential("ArduinoUkulele");
// Set inputs
// Run the Choreo and store the results
TweetsResultSet tweetsResults = tweetsChoreo.run();
// retrieve the results as JSON
JSONObject results = parseJSONObject(tweetsResults.getResponse());
// retrieve the statuses from the results
JSONArray statuses = results.getJSONArray("statuses");
// loop through the statuses
for (int i = 0; i < statuses.size(); i++){
JSONObject status = statuses.getJSONObject(i);
println(status.getString("text"));
println(" -- -- -- -- -- -- -- -- -- -- -- -- -- -- ");
myPort.write(status); // THIS IS THE CODE NOT WORKING WITH JSON
}
}
Arduino:
char val; // Data received from the serial port
int ledPin = 13; // Set the pin to digital I/O 13
void setup(){
pinMode(ledPin, OUTPUT); // Set pin as OUTPUT
Serial.begin(9600); // Start serial communication at 9600 bps
}
void loop(){
if (Serial.available()) { // If data is available to read,
val = Serial.read(); // read it and store it in val
Serial.println(val);
delay(10); // Wait 10 milliseconds for next reading
}
}
I'm sure I'm just looking for a certain command - once I've received the data I'm just looking to turn the LED on based on a new hashtag being receieved. Any help would be greatly appreciated!
Cheers
Arthur
write() method cannot take JSONObject as input, only byte[], String. But you already have everything you need: just use getString() method as you are doing it two lines above (using appropriate key string, which you should know from API that you are using on top of JSON):
myPort.write(status.getString("text"));
Related
I am new to completableFuture, what I am trying to do is I have this logic below in spring boot project which I am trying to convert it to the parallel processing approach using completableFuture.
#Transaction
void serviceMethod{
for(Object obj : objList) //objlist can have 10000 objects and its a multi level composite objects
{
//Get corresponding entity obj from the database, if not found throw user exception
//Process i.e. change some fields
}
}
In the above logic sinnce the method is annotated with #Transaction I am not calling JPA save explicitly to save the entity.
Now, I am trying to do parallel processing with the above logic.
#Transaction
void serviceMethod{
for(Object obj : objList) //objlist can have 10000 objects and its a multi level composite objects
{
//Get corresponding entity obj from the database, if not found throw user exception
CompletableFuture<Optional<Obj>> optionalObjFuture = CompletableFuture.supplyAsync( () -> {//get the object from repository})
CompletableFuture<Obj> objFuture = optionalObjFuture.thenApply( optionalObj -> {
if(obj.isPresent()){
return obj.get();
}
else{
throw user exception;
}
})
////Process i.e. change some fields
}
}
Now the question is
what is the approach I have to follow to break the for loop when there is an exception?
How to handle transaction in this scenario. Is there any way to handle transaction without the need to call saveAll on the processed objects stored in datastructure?
For (1), you could split those 10_000 calls into much smaller batches. For example:
public static void main(String[] args) throws Exception {
int innerIterations = 5;
ExecutorService service = Executors.newFixedThreadPool(innerIterations);
for(int i=0;i<10;++i) {
List<CompletableFuture<String>> list = new ArrayList<>();
int j = 0;
for(;j<innerIterations;++j) {
CompletableFuture<Optional<String>> cf = CompletableFuture.supplyAsync(() -> Optional.of("a"), service);
CompletableFuture<String> cf2 = cf.thenApplyAsync(x -> {
if(x.isPresent()) {
return x.get();
} else {
throw new RuntimeException("test");
}
}, Executors.newFixedThreadPool(2));
list.add(cf2);
}
i += j;
CompletableFuture<Void> all5 = CompletableFuture.allOf(list.toArray(new CompletableFuture[0]));
if(all5.isCompletedExceptionally()) {
// log exception, whatever
break;
} else {
List<String> set = list.stream().map(CompletableFuture::join).collect(Collectors.toList());
System.out.println(set);
}
}
}
This does a couple of things:
splits the initial 10 into two batches of 5.
call CompletableFuture::allOf on those 5 futures. Read the documentation to see that if at least one future fails from those 5, then all5 failed also.
if all5 did not fail (that is all5.isCompletedExceptionally() did not pass), call CompletableFuture::join to get all of the results. There will be no "joining" really, since the previous allOff already waited for them to be completed.
For the second question - you can't. You will need to create a transaction manually, but Spring makes it rather easy.
I'm using Camel 2.15.3 and camel-netty4, and since upgrading from camel-netty3, I'm having problems receiving full JSON messages via UDP. Each JSON message is about 3 to 5 kbytes, but my MessageToMessageDecoder implementation is only giving me the first 2048 (i.e. 2k bytes). From a test program, I send in one UDP message, and from my debug prints within my MessageToMessageDecoder it shows that the decode() method is only called once.
I'm currently reading through Netty In Action, but i see this in my log file: UnpooledUnsafeDirectByteBuf(ridx: 0, widx: 2048, cap: 2048))
I desperately need to get this fixed in production, and just need to be able to receive JSON messasges via UDP and send them through my Camel routes. I'm confused about what is the best framing (if any) to use?
With netty3 this was working fine and I had a UdpPacketDecoder implements ChannelUpstreamHandler that invoked Channels.fireMessageReceived(ctx, message, me.getRemoteAddress()) to fire the message to the next handler and it seemed to work fine.
My route looks like the below. It consumes from netty4:udp and produces to a SEDA queue, just for now while testing:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<route startupOrder="104" customId="true" id="ROUTE_ID_RAW_CQMS_EVENTS" xmlns="http://camel.apache.org/schema/spring">
<from uri="netty4:udp://devserver-09.dev.s.mission.net:11111?serverPipelineFactory=#CQMS_SERVER_PIPELINE_FACTORY_ROUTE_ID_RAW_CQMS_EVENTS&keepAlive=true&sync=false&receiveBufferSize=26214400&sendBufferSize=26214400&allowDefaultCodec=false&disconnectOnNoReply=false&receiveBufferSizePredictor=8192"/>
<setProperty propertyName="CamelCharsetName" id="setProperty1">
<expressionDefinition>iso-8859-1</expressionDefinition>
</setProperty>
<threads poolSize="7" maxPoolSize="14" threadName="threads_ROUTE_ID_RAW_CQMS_EVENTS" callerRunsWhenRejected="true" id="threads1">
<to uri="seda:SEDA_INPUT_QUEUE_102?size=200000&concurrentConsumers=10&waitForTaskToComplete=Never&failIfNoConsumers=true&timeout=10000" id="to1"/>
<setProperty propertyName="CamelCharsetName" id="setProperty2">
<expressionDefinition>iso-8859-1</expressionDefinition>
</setProperty>
</threads>
</route>
I print out the received DatagramPacket, which shows this: UnpooledUnsafeDirectByteBuf(ridx: 0, widx: 2048, cap: 2048))
Here is my MessageToMessageDecoder implementation:
package com.mission.mplr.multiprotocollistenerrouter;
import com.vonage.mplr.utils.MiscUtils;
import io.netty.channel.ChannelHandlerContext; // Represents the "binding" between a ChannelHandler and the ChannelPipeline.
import io.netty.channel.socket.DatagramPacket;
import io.netty.handler.codec.MessageToMessageDecoder;
import java.nio.charset.Charset;
import java.util.List;
import org.slf4j.Logger; // The org.slf4j.Logger interface is the main user entry point of SLF4J API.
import org.slf4j.LoggerFactory; // Utility class producing Loggers for various logging APIs, most notably for log4j.
public class UdpDatagramDecoder extends MessageToMessageDecoder<DatagramPacket> {
private static final Logger logger = LoggerFactory.getLogger(UdpDatagramDecoder.class);
private static final Logger errorLogger = LoggerFactory.getLogger("ERROR_LOGGER");
private final String CHARSET_NAME;
UdpDatagramDecoder(String charsetName) {
this.CHARSET_NAME = charsetName;
}
#Override
public boolean acceptInboundMessage(Object msg) throws Exception {
return true;
}
#Override
protected void decode(ChannelHandlerContext chc, DatagramPacket packet, List out) throws Exception {
logger.info("decode(): ENTER");
logger.info("decode(): Received datagram = {}", packet);
String packetAsString = packet.content().toString(Charset.forName(CHARSET_NAME));
if(packetAsString == null) {
return; // Nothing to do
} else {
out.add(packetAsString);
packet.retain();
}
logger.info("decode(): bodyBytesAsString[size={}] = {}", packetAsString.length(), packetAsString);
String bodyBytesAsHex = MiscUtils.stringAsHex(packetAsString, CHARSET_NAME);
logger.info("decode(): bodyBytesAsHex[size={}] = {}", bodyBytesAsHex.length(), bodyBytesAsHex);
logger.info("decode(): EXIT");
}
}
// ------------- end --------------
My server pipeline has this initChannel() implementation:
#Override
protected void initChannel(Channel ch) throws Exception {
logger.trace("initChannel(): ENTER");
ChannelPipeline channelPipeline = ch.pipeline();
serverInvoked = true;
String theSourceRouteId = consumer.getRoute().getId();
logger.debug("initChannel(): consumer = {}, theSourceRouteId = {}", consumer.toString(), theSourceRouteId);
// -------------------------------------------------------------------
// Here we add the custom UDP datagram decoder. Decoders are typically
// stateful, thus we create a new instance with every pipeline.
// -------------------------------------------------------------------
String udpPacketDecoderName = "CQMS_UDP_DATAGRAM_DECODER_" + theSourceRouteId;
logger.debug("initChannel(): Adding {}", udpPacketDecoderName);
channelPipeline.addLast(udpPacketDecoderName, new UdpDatagramDecoder(CHARSET_NAME));
// -----------------------------------------------------------------------------------------
// Default Camel ServerChannelHandler for the consumer, to allow Camel to route the message.
// -----------------------------------------------------------------------------------------
String serverChannelHandlerName = "CQMS_SERVER_CHANNEL_HANDLER_" + theSourceRouteId;
logger.debug("initChannel(): Adding {}", serverChannelHandlerName);
channelPipeline.addLast(serverChannelHandlerName, new ServerChannelHandler(consumer));
logger.trace("initChannel(): EXIT");
}
Netty uses 2048 as upper limit for datagram packets by default. You can change this via setting your own instance of FixedRecvByteBufAllocator on the Bootstrap. Not sure how this can be done via Camel though.
Thanks so much Norman! Below is the solution that works for Camel 2.15.3.
Basically, we read the upper limit from the application's configuration and set it within the ServerInitializerFactory's initChannel(Channel ch) method.
#Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline channelPipeline = ch.pipeline();
serverInvoked = true;
// -------------------------------------------------------------------
// Here we add the custom UDP datagram decoder. Decoders are typically
// stateful, thus we create a new instance with every pipeline.
// -------------------------------------------------------------------
String udpDecoderName = "UDP_DECODER_" + theSourceRouteId;
channelPipeline.addLast(udpDecoderName, new UdpPacketDecoder_ADAPTER(CHARSET_NAME));
// ---------------------------------------------------------------------
// Netty4 has default of 2048 bytes as upper limit for datagram packets.
// Here we override the default upper limit based on a config param.
// ---------------------------------------------------------------------
if(ConfigManager.getInstance().getRecvByteBufAllocator() > 0) {
ch.config().setRecvByteBufAllocator(new FixedRecvByteBufAllocator(ConfigManager.getInstance().getRecvByteBufAllocator()));
}
// -----------------------------------------------------------
// Add string encoder (downstream) / string decoder (upstream)
// -----------------------------------------------------------
// For decoding from a ChannelBuffer to a String object
String stringDecoderName = "SERVER_PIPELINE_STRING_DECODER_" + theSourceRouteId;
channelPipeline.addLast(stringDecoderName, STR_DECODER);
// For encoding from a String object into a ChannelBuffer
String stringEncoderName = "SERVER_PIPELINE_STRING_ENCODER_" + theSourceRouteId;
channelPipeline.addLast(stringEncoderName, STR_ENCODER);
// For encoding from a String object into a DatagramPacket
String datagramPacketEncoderName = "SERVER_PIPELINE_DATAGRAM_PACKET_ENCODER_" + theSourceRouteId;
channelPipeline.addLast(datagramPacketEncoderName, DATAGRAM_PACKET_ENCODER);
// -----------------------------------------------------------------------------------------
// Default Camel ServerChannelHandler for the consumer, to allow Camel to route the message.
// -----------------------------------------------------------------------------------------
String serverChannelHandlerName = "SERVER_CHANNEL_HANDLER_" + theSourceRouteId;
channelPipeline.addLast(serverChannelHandlerName, new ServerChannelHandler(consumer));
}
I have created a Windows phone app based on a quiz game. I want that when the user give the correct answer for some question then a small tick mark will be permanently on in the tab of the question.
I want to store score for every question so that i can display that in a place name as 'your score'. And that score will not be reset even if the app is closed.
you could use app IsolatedStorage for saving the file.
reference
#region Save and Load Parameters from the Application Storage
void saveToAppStorage(String ParameterName, String ParameterValue)
{
// use mySettings to access the Apps Storage
IsolatedStorageSettings mySettings = IsolatedStorageSettings.ApplicationSettings;
// check if the paramter is already stored
if (mySettings.Contains(ParameterName))
{
// if parameter exists write the new value
mySettings[ParameterName] = ParameterValue;
}
else
{
// if parameter does not exist create it
mySettings.Add(ParameterName, ParameterValue);
}
}
String loadFromAppStorage(String ParameterName)
{
String returnValue = "_notSet_";
// use mySettings to access the Apps Storage
IsolatedStorageSettings mySettings = IsolatedStorageSettings.ApplicationSettings;
// check if the paramter exists
if (mySettings.Contains(ParameterName))
{
// if parameter exists write the new value
mySettings.TryGetValue<String>(ParameterName, out returnValue);
// alternatively the following statement can be used:
// returnValue = (String)mySettings[ParameterName];
}
return returnValue;
}
#endregion
I want to store json values in my device. Because everytime application takes time to load json values. Instead of doing number of times to load, just want to load entire json values once. and without internet I can work with that. Once internet get connected, the application automatically load json values. How can I do this ?
You Can use Database for that.
This way also you can store it.
Arraylist<ClassName> jsondata=new ArrayList<ClassName>
Here's an example:
public Class ClassName
{
string fname;
string lname;
public void setfname(String fname)
{
this.fname=fname;
}
public void setlname(String lname)
{
this.lname=lname;
}
public String getlname(String lname)
{
return lname;
}
public String getfname(String fname)
{
return fname;
}
You can use SharedPreferences to save the json in application's storage space.
code
/* save */
SharedPreferences pref = context.getSharedPreferences("mydata", MODE_PRIVATE);
Editor editor = pref.edit();
editor.put("myjson", json.toString());
editor.commit();
/* restore */
JSONObject ret = null;
SharedPreferences pref = context.getSharedPreferences("mydata", MODE_PRIVATE);
String jsonStr = pref.getString("myjson", null);
if (!TextUtil.isEmpty(jsonStr)) {
ret = new JSONObject(jsonStr); // need try-catch
}
======
Do the restore every time the app is launching.
For the second part "Once internet get connected, the application automatically load json values."
You need to listen the network state change broadcast. When you get broadcast said the network (or wifi) is connected, grab the newest json from server, replace the json in the memory and save it to SharedPreferences
What is the cause of the error "Invalid padding value" in as3crypto?
Error: PKCS#5:unpad: Invalid padding value. expected [153], found [25]
at com.hurlant.crypto.symmetric::PKCS5/unpad()
at com.hurlant.crypto.symmetric::CTRMode/decrypt()
at com.hurlant.crypto.symmetric::SimpleIVMode/decrypt()
at com.mycompany.myproject::Application$/decrypt()
... (followed by the rest of my application stack)
I think I've previously solved this by making sure that the encrypted data is prepended with the intialization vector (IV), by using the SimpleIVMode wrapper class. In this case, I'm already doing that, though.
I'm not using the Crypto class because minimizing download size is important.
Any ideas?
My abstraction code (in Application class):
protected static var cipher:ICipher =
new SimpleIVMode(
new CTRMode(
new AESKey( Hex.toArray("53c12a8eb8612733ec817290580c3d") // not actual key
))
);
public static function encrypt(d:ByteArray):ByteArray {
d.position = 0;
cipher.encrypt(d);
d.position = 0;
return d;
}
public static function decrypt(d:ByteArray):ByteArray {
d.position = 0;
cipher.decrypt(d); // THIS LINE THROWS
d.position = 0;
return d;
}
All that d.position = 0 stuff is my paranoia.
The encryption code:
// we first have to serialize the object to a ByteArray, then encrypt that data.
var encryptedValue:ByteArray = new ByteArray();
encryptedValue.writeObject(objectToEncrypt);
encryptedValue.position = 0; // paranoia?
Application.encrypt(encryptedValue);
so.setProperty(key, encryptedValue); // save it in my SharedObject
Now the code that causes the error:
var data:ByteArray = so.data[key]; // get the byte array out of storage.
trace(data.length); // Check that it's real... I get 553 bytes
Application.decrypt(data); // THIS LINE THROWS
i think you should extend memory size of your SharedObject, like
so.flush(1000000000000000);