How to access a nested structure using PyADS - plc

I have two structures defined in TwinCAT3 like so:
TYPE ADSUWDisplay :
STRUCT
sYarn : STRING;
sNextYarn : STRING;
lLength : REAL;
iPosition : INT;
sYarnSpec : STRING;
iPackageCount : INT;
iPackageTotalCount : INT;
iCount : INT;
iTotalCount : INT;
sUpcomingYarn : STRING;
sUpcomingYarnSpec : STRING;
sUWMessage : STRING;
sThreadUp : STRING;
END_STRUCT
END_TYPE
TYPE ADSRemoteDisplay :
STRUCT
iUW : INT;
iCount : INT;
sState : STRING
iStateNo : INT;
sRobotMessage : STRING;
adsUWDisplay : ARRAY[0..5] OF ADSUWDisplay;
END_STRUCT
END_TYPE
As you can see, ADSUWDisplay is nested inside ADSRemoteDisplay.
How can I access ADSUWDisplay using PyADS?
More specifically, how do I declare my Structure defs for use in pyads.connection.read_structure_by_name()?
Please help!
Thanks

You can read out a struct as follows, from the pyads docs:
Use the parameter structure_def to define the structure and array_size to define the size of the array.
>>> structure_def = (
("i", pyads.PLCTYPE_INT, 1),
("s", pyads.PLCTYPE_STRING, 1)
)
>>> symbol = plc.get_symbol("MyStructure", structure_def=structure_def, array_size=2)
>>> symbol.write([{"i": 1, " "s": "foo"}, {"i": 2, "s": "bar"}])
>>> symbol.read()
[{"i": 1, " "s": "foo"}, {"i": 2, "s": "bar"}]
Not sure how to define a nested struct. I guess you can try to add a nested tuple in structure_def, e.g.:
structure_def = (
("i", pyads.PLCTYPE_INT, 1),
(
("s1", pyads.PLCTYPE_STRING, 1),
("s2", pyads.PLCTYPE_STRING, 1)
)
)

Related

How to create a Hash in Neo4j from given string?

I do the following
CREATE (p:person { FirstName:"M", LastName: "H" , Language: "en", hash: apoc.util.sha512('1234567','salt')});
Error:
Function call does not provide the required number of arguments: expected 1 got 2.
Function apoc.util.sha512 has signature: apoc.util.sha512(values :: LIST? OF ANY?) :: STRING?
meaning that it expects 1 argument of type LIST? OF ANY?
Description: apoc.util.sha512([values]) | computes the sha512 of the concatenation of all string values of the list (line 2, column 73 (offset: 73))
"CREATE (p:person { FirstName:"M", LastName: "H" , Language: "en", hash: apoc.util.sha512('1234567','salt')});"
what is a Type of List argument?
thanks rob
Have it - i used []
CREATE (p:person { FirstName:"M", LastName: "H" , Language: "de", hash: apoc.util.sha512(["1234567","salt"])});

Can't advance past endIndex Swift

Something wrong with String Index when checking and deleting symbols. How can I improve it?
func romanToInt(_ s: String) -> Int {
let romanDigits = ["I" : 1,
"V" : 5,
"X" : 10,
"L" : 50,
"C" : 100,
"D" : 500,
"M" : 1000]
let romanSums = ["IV" : 4,
"IX" : 9,
"XL" : 40,
"XC" : 90,
"CD" : 400,
"CM" : 900]
var sum = 0
var str = s
var charIndex = str.startIndex
for index in str.indices {
if index != str.index(before: str.endIndex) {
charIndex = str.index(after: index)
} else {
charIndex = str.index(before: str.endIndex)
}
let chars = String(str[index]) + String(str[charIndex])
if romanSums[chars] != nil {
print(chars)
str.remove(at: charIndex)
sum += romanSums[chars]!
print(sum)
} else {
let char = String(str[index])
print(char)
sum += romanDigits[char]!
print(sum)
}
print(str)
}
return sum
}
let check = romanToInt("MCMXCIV")
CONSOLE LOG:
M
1000
MCMXCIV
CM
1900
MCXCIV
XC
1990
MCXIV
IV
1994
MCXI
Fatal error: Can't advance past endIndex
You are modifying the string you are iterating over, so your indices become invalid. Instead, you could add a skipChar boolean that says that you've already handled the next character and then skip that character by executing continue:
func romanToInt(_ s: String) -> Int {
let romanDigits = ["I" : 1,
"V" : 5,
"X" : 10,
"L" : 50,
"C" : 100,
"D" : 500,
"M" : 1000]
let romanSums = ["IV" : 4,
"IX" : 9,
"XL" : 40,
"XC" : 90,
"CD" : 400,
"CM" : 900]
var sum = 0
var str = s
var charIndex = str.startIndex
var skipChar = false
for index in str.indices {
if skipChar {
skipChar = false
continue
}
if index != str.index(before: str.endIndex) {
charIndex = str.index(after: index)
} else {
charIndex = str.index(before: str.endIndex)
}
let chars = String(str[index]) + String(str[charIndex])
if romanSums[chars] != nil {
print(chars)
skipChar = true
sum += romanSums[chars]!
print(sum)
} else {
let char = String(str[index])
print(char)
sum += romanDigits[char]!
print(sum)
}
print(str)
}
return sum
}
let check = romanToInt("MCMXCIV")
print(check)
1994
for index in str.indices {
...
str.remove(at: charIndex)
It is not valid to modify a string while you are iterating over it. str.indices is fetched one time here, and is no longer valid once you've modified the underlying string.
I'm sure there will be a lot of implementations of this because it's the kind of small, fun problem that attracts implementations. So why not? This just screams recursion to me.
let romanDigits: [Substring: Int] = ["I" : 1,
"V" : 5,
"X" : 10,
"L" : 50,
"C" : 100,
"D" : 500,
"M" : 1000]
let romanSums: [Substring: Int] = ["IV" : 4,
"IX" : 9,
"XL" : 40,
"XC" : 90,
"CD" : 400,
"CM" : 900]
func romanToInt<S: StringProtocol>(_ s: S) -> Int
where S.SubSequence == Substring {
if s.isEmpty { return 0 }
if let value = romanSums[s.prefix(2)] {
return value + romanToInt(s.dropFirst(2))
} else if let value = romanDigits[s.prefix(1)] {
return value + romanToInt(s.dropFirst(1))
} else {
fatalError("Invalid string")
}
}
let check = romanToInt("MCMXCIV")
Of course this doesn't really check for valid sequences, so it's kind of junk. "IIIIXXIII" is kind of gibberish, but it works. But it's in keeping with the original approach.
Use reduce to make it flow here:
func romanToInt(_ s: String) -> Int {
if s.isEmpty {return 0}
let romanDigits = ["I" : 1,
"V" : 5,
"X" : 10,
"L" : 50,
"C" : 100,
"D" : 500,
"M" : 1000]
let romanSums = ["IV" : 4,
"IX" : 9,
"XL" : 40,
"XC" : 90,
"CD" : 400,
"CM" : 900]
return s.dropFirst().reduce((s.first!, romanDigits["\(s.first!)"]!)){
return ( $1, //current char
$0.1 + //previous sum
(romanSums["\($0.0)\($1)"] //add double value
?? ((romanDigits["\($1)"]!). + romanDigits["\($0.0)"]!)) //or single value and add duplicated
- romanDigits["\($0.0)"]!) // minus duplicated
}.1
}
print(romanToInt("MCMXCIV")). //1994
You are mutating str inside the loop, its end index is going change, in this case it gets lower than its original value. You can fix your code by checking that you haven't exceeded the endIndex on each iteration by using a while loop :
var index = str.startIndex
while index < str.endIndex {
...
//Before the closing curly brace of the while loop
index = str.index(after: index)
}
I was trying to reproduce a crash reported by one my users with the same message Can't advance past endIndex but I was not able to do it. Your code helped me figure out that this error changed in later versions of swift.
Your same code would report cannot increment beyond endIndex with swift 4.x runtime libraries, and String index is out of bounds with 5.x. The exact version numbers for the changes I do not know. But I suspect it is 4.0.0 and 5.0.0.-

How to retrieve []bson.M type of map

How to retrieve multidimensional []bson.M type of map
The data in mongo is like
"taskData" : {
"createdOn" : ISODate("2016-02-20T21:23:11.903Z"),
"Task_content" : "#bob",
"Priority" : "2",
"owner_Uname" : "alice"
}
The code through which i tried to access it
var n []bson.M
e := collection.Find(bson.M{"users."+strconv.Itoa(j)+".user_name" : r.FormValue("value[userName]")}).Select(bson.M{"taskData.owner_Uname":1,"_id":0}).All(&n)
if e != nil {
fmt.Println("Error : ",e)
}else{
fmt.Println(n[0]["taskData"])
}
getting output like this
map[owner_Uname:alice]
I need to access this resultant string with another query.
It is a interface i tried to convert it to simple map
newMap :=n[0]["taskData"].(map[string]interface{})but it gives me an runtime error interface conversion: interface {} is bson.M, not map[string]interface {}
result := rawData{}
err := collection.Find(bson.M{"user_name":n[0]["taskData"]["owner_Uname"]}).All(&result)
Now I want to use it in above query ...
Kindly help me out. Thanks in advance
Edit :-
The data in mongo is like
{
"_id" : ObjectId("56bf128f5a9a6a0ebfdd5075"),
"deadLine" : {
"Start_time" : ISODate("2016-05-24T00:00:00Z"),
"End_time" : ISODate("2016-05-29T00:00:00Z")
},
},
"taskData" : {
"createdOn" : ISODate("2016-02-20T21:23:11.903Z"),
"Task_content" : "#bob",
"Priority" : "2",
"owner_Uname" : "alice"
},
"group" : {
"1" : {
"grp_name" : "grp"
},
"2" : {
"grp_name" : "secondGrp"
}
}
That will work me too if it is done with nested struct or map in struct
I'll provide you with a general example to help you understand, since SO is not a free coding service, but a platform where peers help each other to take a grasp on the problem.
My approach is not to use bson.M at all for the returned value.
package main
import (
"fmt"
"time"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
type Baz struct {
Date time.Time
Value int
}
type Bar struct {
Name string
Baz []Baz
}
type Foo struct {
Owner string
hidden int
Bar Bar
}
const (
ds = "localhost:27017"
db = "test"
coll = "nestdemo"
)
func main() {
o := Foo{
Owner: "me",
hidden: 1,
Bar: Bar{
Name: "funky",
Baz: []Baz{
Baz{Date: time.Now(), Value: 42},
},
},
}
// CHECK ERRORS in production environments
conn, _ := mgo.Dial(ds)
defer conn.Close()
c := conn.DB(db).C(coll)
c.Insert(o)
l := &Foo{}
c.Find(bson.M{"owner": "me"}).One(l)
fmt.Printf("Loaded data: %+v\n", l)
fmt.Printf(
"You got your answer to life, the universe and all the rest at %s: %d\n",
l.Bar.Baz[0].Date.Format(time.Kitchen), l.Bar.Baz[0].Value,
)
}
You can run this program on you local machine (with the constants adjusted as needed), which should give you an output looking like this:
$ go run main.go
Loaded data: &{Owner:me hidden:0 Bar:{Name:funky Baz:[{Date:2016-02-24 09:00:06.471 +0100 CET Value:42}]}}
You got your answer to life, the universe and all the rest at 9:00AM: 42
The entry in the according collection should read something like this:
{
"_id" : ObjectId("56cd6306538ba56563bdab76"),
"owner" : "me",
"bar" : {
"name" : "funky",
"baz" : [
{
"date" : ISODate("2016-02-24T08:00:06.471Z"),
"value" : 42
}
]
}
}
A few things are to note here.
I didn't need a single character in my struct definitions to have the structs marshaled to and marshaled from BSON. It was done automagically by mgo according to the rules described in the docs. However, you can customize the behavior of the (un-)marshaling, as described there.
Unexported fields (hidden in this example) take their zero value upon unmarshalling – keep that in mind, it can bite you in the neck.
There is no need to use bson.M to handle your data, which makes life a lot easier – no manual type conversions, for example.
In summary: All you need to do is to create a struct your data can be unmarhaled into. Then you can access the various fields as usual, without string fiddling and alike. That's bit of work, but a rather trivial one, as you can see.
Note: The data model you have shown is both syntactically and conceptually incorrect. Setting aside the former for now: It is a very bad practice to have values as keys, as shown in the group subdoc. This will always force you to deal with string parsing back and forth, making your life with MongoDB as complicated as it can get as a developer.
My above suggestion assumes you will correct that into something like:
{
…
groups:[
{grp_id: 1, grp_name: "grp"},
{grp_id: 2, grp_name: "secondGrp"}
]
…
}

How to map a RDD of type org.apache.spark.rdd.RDD[Array[String]]?

I am new to Spark and Scala.
I have an RDD that is of type org.apache.spark.rdd.RDD[Array[String]].
Here is a listing from myRdd.take(3).
Array(Array(1, 2524474, CBSGPRS, 1, 2015-09-09 10:42:03, 0, 47880, 302001131103734, NAT, "", 502161081073570, "", BLANK, UNK, "", "", "", MV_PVC, BLANK, 1, "", 0, 475078439, 41131;0;0, "", 102651;0;0, 3|3), Array(2, 2524516, CBSGPRS, 1, 2015-09-09 23:42:14, 0, 1260, 302001131104272, NAT, "", 502161081074085, "", BLANK, UNK, "", "", "", MV_PVC, BLANK, 1, "", 0, 2044745984, 3652;0;0, "", 8636;0;0, 3|3), Array(3, 2524545, CBSGPRS, 1, 2015-09-09 14:56:55, 0, 32886, 302001131101629, NAT, "", 502161081071599, "", BLANK, UNK, "", "", "", MV_PVC, BLANK, 1, "", 0, 1956194307, 14164657;0;0, "", 18231194;0;0, 3|3))
I am trying to map it as follows ..
var gprsMap = frows.collect().map{ tuple =>
// bind variables to the tuple
var (recKey, origRecKey, recTypeId, durSpanId, timestamp, prevConvDur, convDur,
msisdn, callType, aPtyCellId, aPtyImsi, aPtyMsrn, bPtyNbr, bPtyNbrTypeId,
bPtyCellId, bPtyImsi, bPtyMsrn, inTrgId, outTrgId, callStatusId, suppSvcId, provChgAmt,
genFld1, genFld2, genFld3, genFld4, genFld5) = tuple
var dtm = timestamp.split(" ");
var idx = timestamp indexOf ' '
var dt = timestamp slice(0, idx)
var tm = timestamp slice(idx + 1, timestamp.length)
// return the results tuple
((dtm(0), msisdn, callType, recTypeId, provChgAmt), (convDur))
}
I keep getting error:
error: object Tuple27 is not a member of package scala.
I am not sure what the error is. Can someone help?
The problem is that Scala only supports tuples with up to 22 fields. Additionally, your frows: RDD[Array[String]] contains Array[String] as elements. Thus, also your tuple variable in the map function is of type Array[String]. Therefore, it is not possible to unapply the variable tuple into a tuple.
But what you can do is accessing the elements of the array directly via indices.
val recKey = tuple(0)
val timestamp = tuple(4)
...

unstructred inner document with mgo

I have a document which has this following structure
{ "_id" : "736722976", "value" : { "total_visit" : 4, "FIFA World Cup 2014" : 1, "Germany" : 1, "Algeria" : 1, "Thomas Muller" : 1, "Mesut Ozil" : 1, "Monsoon" : 1, "India Meteorological Department (IMD)" : 1, "Web Exclusive" : 2, "Specials" : 1, "Tapas Pal" : 1, "Twitter Trends" : 1, "Sunanda Pushkar" : 1, "Shashi Tharoor" : 1, "AIIMS" : 1, "special" : 1 } }
THE MOST IMPORTANT thing is that the sub document structure under the key "value" is variable so I can not create a structure for that. I tried to follow the suggestion here - Unstructured MongoDB collections with mgo
And I came with this code ---
package main
import ("fmt"
"labix.org/v2/mgo" //importing mgo
"labix.org/v2/mgo/bson"
_ "reflect"
)
type AnalysisStruct struct{
Id string `bson:"_id,omitempty"`
Value bson.M `bson:",inline"`
}
func main() {
var m AnalysisStruct
//connecting to localhost mongodb
session, err := mgo.Dial("localhost")
if err != nil {
panic(err)
}
defer session.Close()
c := session.DB("my_analysis_db").C("analysis_mid_2")
iter := c.Find(nil).Iter()
for{
if iter.Next(&m){
fmt.Println(m.Value["value"]["total_visit"])
}else{
break
}
}
}
When I try to build this using go build -v -o analyzer it shows me this error---
./analyzer.go:32: invalid operation: m.Value["value"]["total_visit"] (index of type interface {})
I am terribly stuck with this. Can not get anything going. Please can somebody help?
Thanks
I cam up with this code after doing some research. Not the most optimized one for sure. But for my case it works. Took help from
http://blog.denevell.org/golang-interface-type-assertions-switch.html
https://groups.google.com/forum/#!topic/mgo-users/JYE-CP15az4
package main
import ("fmt"
"labix.org/v2/mgo" //importing mgo
"labix.org/v2/mgo/bson"
_ "reflect"
)
type AnalysisStruct struct{
Id string `bson:"_id,omitempty"`
Value bson.M `bson:",inline"`
}
func main() {
var m AnalysisStruct
//connecting to localhost mongodb
session, err := mgo.Dial("localhost")
if err != nil {
panic(err)
}
defer session.Close()
c := session.DB("consumergenepool_db").C("analysis_mid_2")
iter := c.Find(nil).Iter()
for{
if iter.Next(&m){
s := m.Value["value"].(bson.M)
data, _ := bson.Marshal(s)
var m bson.M
_ = bson.Unmarshal(data, &m)
fmt.Println(m)
for k, v := range m{
fmt.Print(k)
fmt.Print(" :: ")
fmt.Println(v)
}
}else{
break
}
}
}
Let me know your thoughts on this.
Thanks
When testing something new always use a lot of fmt.Printf's to get a feel for it, that being said.
Value bson.M `bson:",inline"`
Should be
Value bson.M `bson:"value,omitempty"`
And
fmt.Println(m.Value["value"]["total_visit"])
Should be:
fmt.Printf("%#v\n", m)
fmt.Println(m.Value["total_visit"])
Your m.Value is "value", so you can use m.Value["total_visit"] directly.
playground
//edit
You can only use inline to catch any fields that that aren't a part of the original struct, but since your struct only has 2 fields (Id and Value), you don't need it.
Now if you were to keep ,inline you would use it like this:
if v, ok := m.Value["value"].(bson.M); ok {
fmt.Println(v["total_visit"])
}
Because m.Value["value"] is an interface{}, you have to type assert it back to it's original value, bson.M before you could use it.