I have been attempting to use streams in swift to interface with a java socket server (I don't believe the java server is my problem) but when I attempt to write with an OutputStream my string includes a bunch of extra garbage that was not in my original string
The code currently looks like this:
var maxWriteLength = 4096
func sendMessage(msg: String) {
let encodedDataArray = [UInt8](msg.utf8)
outputStream.write(encodedDataArray, maxLength: maxWriteLength)
}
However when I give it an input of "hi" it returns an ouput of:
Echo: hi���8B��,rؾ�؇��allowCloudBackup؇��allowAppInstallation؇��safariForceFraudWarning�&��q���ޙTh�C��=wthread��&��q����������������8$��N��8$���0'}��#�
Echo: �'��q����������p�g�iYh�C���iYh�C��
Echo: D�#D�8״
Echo: pV���؇��requireAlphanumeric؇��allowCellularHDUploadsInternational-Key_2��
and much much more
I have seen other posts suggesting that you should use encodedDataArray.count instead of a maxWriteLength however when I have used this the OutputStream will not write anything.
Thanks in advance.
For future people who struggle with this it was indeed the way the server was handling messages (I went back to check it). The problem was that I was using Scanner.nextLine() and had no \n inside of the swift portion of my code. If you are using an array make sure that you add + "\n" to your string before it is made into an array otherwise the bytes for \n will not be written. The final code looked like this:
func sendMessage(msg: String) {
var finalMsg = msg + "\n"
let encodedDataArray = [UInt8](finalMsg.utf8)
outputStream.write(encodedDataArray, maxLength: encodedDataArray.count)
}
Related
There seem to be other answers the this on stack overflow but nothing that is specific to swift.
I am generating a CSV from an Site Object containing 3 properties
Struct SiteDetails {
var siteName:String?
var siteType: String?
var siteUrl: String?
}
The problem is that siteName may contain a comma so its making it really hard to convert back from CSV into a object when I read the CSV file back as some lines have 4 or more CSV elements.
Here is the code I am using to export to CSV:
func convertToCSV(sites: [SiteDetails]) -> String {
var siteAsCSV = ""
siteAsCSV.appendContentsOf("siteName,siteType,siteUrl\n")
for site in sites {
siteAsCSV.appendContentsOf("\(site.siteName),\(site.siteType),\(site.siteUrl)\n")
}
}
Any ideas how to stop this extra comma issue?
The CSV specification suggests to wrap all fields containing special characters in double quotes.
I managed to get this working using the modification of adding the double quotes to each field. In Swift, this requires you to escape the quotation mark which looks like its not going to run when you look at Xcode's syntax highlighting, but it works fine.
func convertToCSV(sites: [SiteDetails]) -> String {
var SiteAsCSV = ""
SiteAsCSV.appendContentsOf("siteName,siteType,siteUrl\n")
for site in sites {
SiteAsCSV.appendContentsOf("\"\(site.SiteName)\",\"\(site.Sitetype)\",\"\(site.SiteUrl)\"\n")
}
}
I want to use the can_msgs/Frame.msg for decoding can messages using db.decode_message(Frame.id, Frame.data) but it is giving error
I want to try and write a new Frame.msg format but will it help?
def callback(Frame):
rospy.loginfo(rospy.get_caller_id() + "I heard %s", Frame.data)
Temp = db.decode_message(Frame.id, Frame.data)
temp.data = Temp
pub.publish(temp)
I want to print the message in the dbc format that the cantools package helps decoding.
Error:
File "safa.py", line 42, in callback
temp = db.decode_message(Frame.id, Frame.data)
File "build/bdist.linux-x86_64/egg/cantools/database/can/database.py", line 379, in decode_message
message = self._name_to_message[frame_id_or_name]
KeyError: 10
Looking at the cantools documentation for db.decode_message, the KeyError is a bad description/error msg for the following.
db is a database (class cantools.database.can.Database), which stores all the weird encodings we may choose to use with cantools. To decode a message, it must already have an encoding stored within it, using one of the db.add_* methods with the class.
Edit:
The definition of the can_msgs/Frame is
std_msgs/Header header
uint32 id
bool is_rtr
bool is_extended
bool is_error
uint8 dlc
uint8[8] data
The data term requires an array/list of 8 uint8 values, not a string. Any CANbus data encoding must finish in this form.
Additionally, ROS provides an interface to the CANbus already: socketcan_bridge can be called in a launch file with your node at the same time.
Before you can decode messages you should setup the database e.g by loading a dbc file:
try:
dbc_file_object = open(dbc_file, 'r')
except IOError as e:
rospy.loginfo('Unable to open file {}'.format(e))
sys.exit(-1)
self.db = cantools.db.load(dbc_file_object)
I have the following code:
buff=esp.flash_read(esp.flash_user_start(),50)
print(buff)
I get the following output from print:
bytearray(b'{"ssid": "mySSID", "password": "myPASSWD"}\xff\xff\xff\xff\xff\xff')
What I want to do is get the json in buff. What is the correct "Python-way" to do that?
buff is a Python bytes object, as shown by the print output beginning with b'. To convert this into a string you need to decode it.
In standard Python you could use
buff.decode(errors='ignore')
Note that without specifying errors=ignore you would get a UnicodeDecodeError because the \xff bytes aren't valid in the default encoding, which is UTF-8; presumably they're padding and you want to ignore them.
If that works on the ESP8266, great! However this from the MicroPython docs suggests the keyword syntax might not be implemented - I don't have an ESP8266 to test it. If not then you may need to remove the padding characters yourself:
textLength = find(buff, b'\xff')
text = buff[0:textLength].decode()
or simply:
text = buff[0:buff.find(b'\xff')].decode()
If decode isn't implemented either, which it isn't in the online MicroPython interpreter, you can use str:
text = str(buff[0:find(buff, b'\xff')], 'utf-8')
Here you have to specify explicitly that you're decoding from UTF-8 (or whatever encoding you specify).
However if what you're really after is the values encoded in the JSON, you should be able to use the json module to retrieve them into a dict:
import json
j = json.loads(buff[0:buff.find(b'\xff')])
ssid = j['ssid']
password = j['password']
CONCLUSION:
For some reason the flow wouldn't let me convert the incoming message to a BLOB by changing the Message Domain property of the Input Node so I added a Reset Content Descriptor node before the Compute Node with the code from the accepted answer. On the line that parses the XML and creates the XMLNSC Child for the message I was getting a 'CHARACTER:Invalid wire format received' error so I took that line out and added another Reset Content Descriptor node after the Compute Node instead. Now it parses and replaces the Unicode characters with spaces. So now it doesn't crash.
Here is the code for the added Compute Node:
CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN
DECLARE NonPrintable BLOB X'0001020304050607080B0C0E0F101112131415161718191A1B1C1D1E1F7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF1F2F3F4F5F6F7F8F9FAFBFCFDFEFF';
DECLARE Printable BLOB X'20202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020';
DECLARE Fixed BLOB TRANSLATE(InputRoot.BLOB.BLOB, NonPrintable, Printable);
SET OutputRoot = InputRoot;
SET OutputRoot.BLOB.BLOB = Fixed;
RETURN TRUE;
END;
UPDATE:
The message is being parsed as XML using XMLNSC. Thought that would cause a problem, but it does not appear to be.
Now I'm using PHP. I've created a node to plug into the legacy flow. Here's the relevant code:
class fixIncompetence {
function evaluate ($output_assembly,$input_assembly) {
$output_assembly->MRM = $input_assembly->MRM;
$output_assembly->MQMD = $input_assembly->MQMD;
$tmp = htmlentities($input_assembly->MRM->VALUE_TO_FIX, ENT_HTML5|ENT_SUBSTITUTE,'UTF-8');
if (!empty($tmp)) {
$output_assembly->MRM->VALUE_TO_FIX = $tmp;
}
// Ensure there are no null MRM fields. MessageBroker is strict.
foreach ($output_assembly->MRM as $key => $val) {
if (empty($val)) {
$output_assembly->MRM->$key = '';
}
}
}
}
Right now I'm getting a vague error about read only messages, but before that it wasn't working either.
Original Question:
For some reason I am unable to impress upon the senders of our MQ
messages that smart quotes, endashes, emdashes, and such crash our XML
parser.
I managed to make a working solution with SQL queries, but it wasted
too many resources. Here's the last thing I tried, but it didn't work
either:
CREATE FUNCTION CLEAN(IN STR CHAR) RETURNS CHAR BEGIN
SET STR = REPLACE('–',STR,'–');
SET STR = REPLACE('—',STR,'—');
SET STR = REPLACE('·',STR,'·');
SET STR = REPLACE('“',STR,'“');
SET STR = REPLACE('”',STR,'”');
SET STR = REPLACE('‘',STR,'&lsqo;');
SET STR = REPLACE('’',STR,'’');
SET STR = REPLACE('•',STR,'•');
SET STR = REPLACE('°',STR,'°');
RETURN STR;
END;
As you can see I'm not very good at this. I have tried reading about
various ESQL string functions without much success.
So in ESQL you can use the TRANSLATE function.
The following is a snippet I use to clean up a BLOB containing non-ASCII low hex values so that it then be cast into a usable character string.
You should be able to modify it to change your undesired characters into something more benign. Basically each hex value in NonPrintable gets translated into its positional equivalent in Printable, in this case always a full-stop i.e. x'2E' in ASCII. You'll need to make your BLOB's long enough to cover the desired range of hex values.
DECLARE NonPrintable BLOB X'000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F';
DECLARE Printable BLOB X'2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E';
SET WorkBlob = TRANSLATE(WorkBlob, NonPrintable, Printable);
BTW if messages with invalid characters only come in every now and then I'd probably specify BLOB on the input node and then use something similar to the following to invoke the XMLNSC parser.
CREATE LASTCHILD OF OutputRoot DOMAIN 'XMLNSC'
PARSE(InputRoot.BLOB.BLOB CCSID InputRoot.Properties.CodedCharSetId ENCODING InputRoot.Properties.Encoding);
With the exception terminal wired up you can then correct the BLOB's of any messages containing parser breaking invalid characters before attempting to reparse.
Finally my best wishes as I've had a number of battles over the years with being forced to correct invalid message content in the "Integration Layer" after all that's what it's meant to do.
So I have this crazy problem with comparing 2 strings in ActionScript 2.0
I have a global variable which holds some text (usually it is "statistic") from xml feed
_root.var_name = fields.firstChild.attributes.value;
when I trace() it it gives me the expected message
trace(_root.var_name); // echoes "statistik"
and when I try to use it in conditional statement the rest of code is not being executed because comparing :
if(_root.overskrift == "statistik"){
//do stuff
}
returns false!
I tried also with:
if(_root.overskrift.equals("statistik"))
but with the same result.
Any input will be appreciated.
Years later but on a legacy project I had the same problem and the solution was in a comment to this unanswered question. So let's make it an anwer:
Where var a:String="some harmless but in my case long string" and var b:String="some harmless but in my case long string" but (a==b) -> false the following works just fine: (a.indexOf(b)>=0) -> true. If the String were not found indexOf would give -1. Why the actual string comparison fails I coudn't figure out either. AS2 is ancient and almost obsolete...