I have tried using a Yaml collection of maps in my config file :
Companies:
- code: 11
name: A
country: FR
functionalCurrency: EUR
- code: 12
name: B
country: GB
functionalCurrency: GBP
However, when trying to read it with the type provider, it only finds the first result of the list.
With :
open FSharp.Configuration
type CompaniesConfig = YamlConfig<"Config.yaml">
let config = CompaniesConfig()
the output is :
val config : CompaniesConfig =
Companies:
- code: 11
name: A
country: FR
functionalCurrency: EUR
Trying to parse the code online worked, hence I wonder if that is a library limitation or... ?
Thanks for your help
You need to actually load the file, not only get the schema if you want to work with it directly: config.Load(yamlFile). This should probably more explicit in the documentation. I used the sample file in the link.
#if INTERACTIVE
#r #"..\packages\FSharp.Configuration.0.6.1\lib\net40\FSharp.Configuration.dll"
#endif
open FSharp.Configuration
open System.IO
/// https://github.com/fsprojects/FSharp.Configuration/blob/master/tests/FSharp.Configuration.Tests/Lists.yaml
[<Literal>]
let yamlFile = __SOURCE_DIRECTORY__ + "..\Lists.yaml"
File.Exists yamlFile
type TestConfig = YamlConfig<yamlFile>
let config = TestConfig()
config.Load(yamlFile)
config.items.Count
config.items
And I get both items:
>
val it : int = 2
>
val it : System.Collections.Generic.IList<TestConfig.items_Item_Type> =
seq
[FSharp.Configuration.TestConfig+items_Item_Type
{descrip = "Water Bucket (Filled)";
part_no = "A4786";
price = 147;
quantity = 4;};
FSharp.Configuration.TestConfig+items_Item_Type
{descrip = "High Heeled "Ruby" Slippers";
part_no = "E1628";
price = 10027;
quantity = 1;}]
>
Related
I have incoming BLE beacon data from a gateway in the following format:
{"msg":"advData","gmac":"94A408B02508","obj":
[
{"type":32,"dmac":"AC233FE0784F","data1":"0201060303F1FF1716E2C56DB5DFFB48D2B060D0F5A71096E000000000C564","rssi":-45,"time":"2022-10-13 02:46:24"},
{"type":32,"dmac":"AC233FE078A1","data1":"0201060303F1FF1716E2C56DB5DFFB48D2B060D0F5A71096E000000000C564","rssi":-42,"time":"2022-10-13 02:46:26"}
]
}
and I want to extract the attributes gmac, dmac, rssi, and process attribute data1 and ingest these into influxdb via a telegraf config file.
I can successfully ingest gmac, dmac, and rssi using the below telegraf config:
## Data format to consume.
## Each data format has its own unique set of configuration options, read
## more about them here:
## https://github.com/influxdata/telegraf/blob/master/docs/DATA_FORMATS_INPUT.md
data_format = "json_v2"
tagexclude = ["topic"]
[[inputs.mqtt_consumer.json_v2]]
measurement_name = "a"
timestamp_path = "obj.#.time"
timestamp_format = "unix"
[[inputs.mqtt_consumer.json_v2.tag]]
path = "gmac"
rename = "g"
[[inputs.mqtt_consumer.json_v2.tag]]
path = "obj.#.dmac"
rename = "d"
[[inputs.mqtt_consumer.json_v2.field]]
path = "obj.#.rssi"
type = "int"
rename = "r"
However, I'm not sure how to process the data1 attribute where I need to (1) extract characters 15 and 16 and convert this from a hexadecimal value to an integer, and (2) extract characters 13 and 14 and convert each hexadecimal value to an integer before combining them together as a float (character 13 is the whole number component, character 14 is the decimal component).
Can anybody provide some guidance here?
Many thanks!
Got it working thanks to some help over at Influx Community, I've pasted the relevant section of the telegraf config file if this is of help to anyone else:
data_format = "json_v2"
tagexclude = ["topic"]
[[inputs.mqtt_consumer.json_v2]]
measurement_name = "a"
timestamp_path = "obj.#.time"
timestamp_format = "unix"
[[inputs.mqtt_consumer.json_v2.tag]]
path = "gmac"
# g is gateway MAC address
rename = "g"
[[inputs.mqtt_consumer.json_v2.tag]]
path = "obj.#.dmac"
# d is beacon MAC address
rename = "d"
[[inputs.mqtt_consumer.json_v2.field]]
path = "obj.#.rssi"
type = "int"
# r is RSSI of beacon
rename = "r"
[[inputs.mqtt_consumer.json_v2.field]]
path = "obj.#.data1"
data_type = "string"
[[processors.starlark]]
namepass = ["a"]
source = '''
def apply(metric):
data1 = metric.fields.pop("data1")
tempWhole = int("0x" + data1[26:28], 0)
tempDecimal = int("0x" + data1[28:30], 0)
tempDecimal = tempDecimal / 100
# t is temperature of chip to two decimal points precision
metric.fields["t"] = tempWhole + tempDecimal
# b is battery level in mV
metric.fields["b"] = int("0x" + data1[30:34], 0)
return metric
'''
i have a text file that contains data in the format YEAR, CITY, COUNTRY. data is written as one YEAR, CITY, COUNTRY per line. eg -:
1896, Athens, Greece
1900, Paris, France
Previously i was using the data hard coded like this
local data = {}
data[1] = { year = 1896, city = "Athens", country = "Greece" }
data[2] = { year = 1900, city = "Paris", country = "France" }
data[3] = { year = 1904, city = "St Louis", country = "USA" }
data[4] = { year = 1908, city = "London", country = "UK" }
data[5] = { year = 1912, city = "Stockholm", country = "Sweden" }
data[6] = { year = 1920, city = "Antwerp", country = "Netherlands" }
Now i need to read the lines from the file and get the values in to the private knowledge base "local data = {} "
Cant figure out how to capture multiple values using a single pattern from the data in the file.
My code so far is
local path = system.pathForFile( "olympicData.txt", system.ResourceDirectory )
-- Open the file handle
local file, errorString = io.open( path, "r" )
if not file then
-- Error occurred; output the cause
print( "File error: " .. errorString )
else
-- Read each line of the file
for line in file:lines() do
local i, value = line:match("%d")
table.insert(data, i)
-- Close the file
io.close(file)
end
file = nil
Given that you read a line like
1896, Athens, Greece
You can simply obtain the desired values using captures.
https://www.lua.org/manual/5.3/manual.html#6.4.1
Captures: A pattern can contain sub-patterns enclosed in parentheses; they describe captures. When a match succeeds, the
substrings of the subject string that match captures are stored
(captured) for future use. Captures are numbered according to their
left parentheses. For instance, in the pattern "(a*(.)%w(%s*))", the
part of the string matching "a*(.)%w(%s*)" is stored as the first
capture (and therefore has number 1); the character matching "." is
captured with number 2, and the part matching "%s*" has number 3.
As a special case, the empty capture () captures the current string
position (a number). For instance, if we apply the pattern "()aa()" on
the string "flaaap", there will be two captures: 3 and 5.
local example = "1896, Athens, Greece"
local year, city, country = example:match("(%d+), (%w+), (%w+)")
print(year, city, country)
There is the following code on the AWS documentation page (I simplified):
Table table = Table.LoadTable(client, "ProductCatalog");
var book = new Document();
book["Id"] = 101;
book["Title"] = "Book 101 Title";
book["ISBN"] = "11-11-11-11";
table.PutItem(book);
When I try to the same from Fsharp I get an error:
let seqNumberDocument = Document()
seqNumberDocument.["key"] <- 101
Type constraint mismatch. The type
'int' is not compatible with type
'DynamoDBEntry'
Is there a way to get this working in Fsharp?
You'll need to call the implicit conversion to DynamoDBEntry like this:
let seqNumberDocument = Document()
seqNumberDocument.["key"] <- DynamoDBEntry.op_Implicit 101
F# doesn't itself support implicit conversion by design.
If that looks a bit ugly, you can use the alternative:
let v2 = DynamoDBEntryConversion.V2
let seqNumberDocument = Document()
seqNumberDocument.["key"] <- v2.ConvertToEntry 101
I'm attempting to build a ROM-based Window function using DSPComplex and FixedPoint types, but seem to keep running into the following error:
chisel3.core.Binding$ExpectedHardwareException: vec element 'dsptools.numbers.DspComplex#32' must be hardware, not a bare Chisel type
The source code for my attempt at this looks like the following:
class TaylorWindow(len: Int, window: Seq[FixedPoint]) extends Module {
val io = IO(new Bundle {
val d_valid_in = Input(Bool())
val sample = Input(DspComplex(FixedPoint(16.W, 8.BP), FixedPoint(16.W, 8.BP)))
val windowed_sample = Output(DspComplex(FixedPoint(24.W, 8.BP), FixedPoint(24.W, 8.BP)))
val d_valid_out = Output(Bool())
})
val win_coeff = Vec(window.map(x=>DspComplex(x, FixedPoint(0, 16.W, 8.BP))).toSeq) // ROM storing our coefficients.
io.d_valid_out := io.d_valid_in
val counter = Reg(UInt(10.W))
// Implicit reset
io.windowed_sample:= io.sample * win_coeff(counter)
when(io.d_valid_in) {
counter := counter + 1.U
}
}
println(getVerilog(new TaylorWindow(1024, fp_seq)))
I'm actually reading the coefficients in from a file (this particular window has a complex generation function that I'm doing in Python elsewhere) with the following sequence of steps
val filename = "../generated/taylor_coeffs"
val coeff_file = Source.fromFile(filename).getLines
val double_coeffs = coeff_file.map(x => x.toDouble)
val fp_coeffs = double_coeffs.map(x => FixedPoint.fromDouble(x, 16.W, 8.BP))
val fp_seq = fp_coeffs.toSeq
Does this mean the DSPComplex type isn't able to be translated to Verilog?
Commenting out the win_coeff line seems to make the whole thing generate (but clearly doesn't do what I want it to do)
I think you should try using
val win_coeff = VecInit(window.map(x=>DspComplex.wire(x, FixedPoint.fromDouble(0.0, 16.W, 8.BP))).toSeq) // ROM storing our coefficients.
which will create hardware values like you want. The Vec just creates a Vec of the type specfied
I'm trying to turn on AutoFilter for the users who will consume the data.
open Microsoft.Office.Interop.Excel
let xl = ApplicationClass()
xl.Workbooks.OpenText(fileName...)
let wb = xl.Workbooks.Item(1)
let ws = wb.ActiveSheet :?> Worksheet
let rows = string ws.UsedRange.Rows.Count
// AutoFilter method of Range class failed.
ws.Range("A7:I" + rows).AutoFilter() |> ignore
Thanks for any help you can offer.
According to the documentation, you need to pass 5 parameters to AutoFilter.
Unspecified parameters can be filled by System.Reflection.Missing.Value.
Something like
ws.Range("A7:I" + rows).AutoFilter(1, System.Reflection.Missing.Value,
Excel.XlAutoFilterOperator.xlAnd,
System.Reflection.Missing.Value, true)
|> ignore
should work.