I'm trying to establish connection with kafka server without third party libraries in Rust.
This is the description of kafka server TCP protocol
This is my code:
fn connect() -> Result<(), std::io::Error> {
let stream = TcpStream::connect("localhost:9092").expect("Could not connect");
let mut input_stream = stream.try_clone().unwrap();
input_stream.set_read_timeout(Some(Duration::new(5, 0)));
input_stream.set_write_timeout(Some(Duration::new(5, 0)));
/// HERE IS MY PROBLEM. I DON'T KNOW HOW TO ENCODE KAFKA MESSAGE
let mut data = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
/// api key 0, 0, 0, 0, 0, 0
/// request_api_version 0, 0, 0, 0, 0, 0
/// correlation_id 0, 0, 0, 0, 0, 0,
let mut buffer: Vec<u8> = Vec::with_capacity(1400);
buffer.extend_from_slice(&[0; 100]);
input_stream.write(&mut data)?;
match input_stream.read(&mut buffer) {
Ok(b) => {
println!("read ok - {:?}", String::from_utf8_lossy(&buffer));
}
Err(e) => println!("Error {}", e),
}
Ok(())
}
fn main() {
connect();
}
How to encode this kafka message to byte array ?
Variable data should be an array of bytes
Naive code for creating kafka message of next interface
request_api_key => INT16
request_api_version => INT16
correlation_id => INT32
const int16 = (prevBuffer: Buffer, value: number) => {
const newBuffer = Buffer.alloc(2)
newBuffer.writeInt16BE(value)
return Buffer.concat([prevBuffer, newBuffer]);
}
const int32 = (prevBuffer: Buffer, value: number) => {
const newBuffer = Buffer.alloc(4)
newBuffer.writeInt32BE(value)
return Buffer.concat([prevBuffer, newBuffer]);
}
const payload = int31(int16(int16(Buffer.alloc(0), 3), 0),1);
The code is shamelessly taken from kafkajs
I am learning the Qt 3D module. I found the Qt.matrix4x4 provide different API than QMatrix4x4 in C++ side (by using F1 check the API doc).
look likes Qt.matrix4x4 don't have such scale or rotation operations. even not in autocomplete.
BUT! these functions do exist and work!
var m = Qt.matrix4x4(1, 0, 0, -0.5, 0, 1, 0, 0, 0, 0, 1, 0.5, 0, 0, 0, 1)
m.scale(2)
console.log(m)
// qml: QMatrix4x4(2, 0, 0, -0.5, 0, 2, 0, 0, 0, 0, 2, 0.5, 0, 0, 0, 1)
// the type shows QMatrix4x4
https://doc.qt.io/qt-5/qmatrix4x4.html vs https://doc.qt.io/qt-5/qml-matrix4x4.html
I understand what these is, But why the API show different in API doc and autocomplete?
It is interesting to note that in Qt6 the documentation appears different than Qt5. In Qt6 we see clearly there are methods for constructing the matrix4x4 basic type from a vector and for multiplying them with vectors.
// translate(vector3d)
var m = Qt.matrix4x4();
m.translate(Qt.vector3d(1,2,3));
console.log(m.toString());
// QMatrix4x4(1, 0, 0, 1, 0, 1, 0, 2, 0, 0, 1, 3, 0, 0, 0, 1)
// matrix multiplication
var m = Qt.matrix4x4();
m.translate(Qt.vector3d(1,2,3));
console.log(m.toString());
// QMatrix4x4(1, 0, 0, 1, 0, 1, 0, 2, 0, 0, 1, 3, 0, 0, 0, 1)
// applying a matrix to a vector
var a = Qt.matrix4x4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);
var b = Qt.vector3d(5,6,7);
var c = a.times(b);
console.log(c.toString()); // QVector3D(0.155556, 0.437037, 0.718518)
Note I tried all of the above in Qt5.15.6 but it doesn't work. So it appears that support for this type really kicks in at Qt6.
For further information see: https://doc.qt.io/qt-6/qml-matrix4x4.html
I have this simple controller
#RestController
#RequestMapping("/metrics")
public class MetricsController {
#GetMapping
#ApiOperation("Get metrics by source")
public ResponseEntity<List<Metric>> getMetricBySource(#RequestParam String source) {
if (source.equalsIgnoreCase("recordings")) {
return new ResponseEntity<>(MetricsConstants.RECORDINGS_METRICS, HttpStatus.OK);
} else if (source.equalsIgnoreCase("advertisers")) {
return new ResponseEntity<>(MetricsConstants.ADVERTISERS_METRICS, HttpStatus.OK);
} else if (source.equalsIgnoreCase("publishers")) {
return new ResponseEntity<>(MetricsConstants.PUBLISHERS_METRICS, HttpStatus.OK);
} else if (source.equalsIgnoreCase("partners")) {
return new ResponseEntity<>(MetricsConstants.PARTNERS_METRICS, HttpStatus.OK);
} else if (source.equalsIgnoreCase("products")) {
return new ResponseEntity<>(MetricsConstants.PRODUCTS_METRICS, HttpStatus.OK);
} else if (source.equalsIgnoreCase("regular-users")) {
return new ResponseEntity<>(MetricsConstants.REGULAR_USERS_METRICS, HttpStatus.OK);
}
return null;
}
}
Now, when I'm trying to access the endpoint via
localhost:8099/metrics?source=advertisers
I'm getting the following response
{
"mem": 947258,
"mem.free": 367038,
"processors": 4,
"instance.uptime": 540532,
"uptime": 556754,
"systemload.average": -1,
"heap.committed": 854016,
"heap.init": 260096,
"heap.used": 486977,
"heap": 3699200,
"nonheap.committed": 95312,
"nonheap.init": 2496,
"nonheap.used": 93242,
"nonheap": 0,
"threads.peak": 61,
"threads.daemon": 37,
"threads.totalStarted": 128,
"threads": 53,
"classes": 13916,
"classes.loaded": 13916,
"classes.unloaded": 0,
"gc.ps_scavenge.count": 13,
"gc.ps_scavenge.time": 150,
"gc.ps_marksweep.count": 3,
"gc.ps_marksweep.time": 341,
"counter.servo.eurekaclient.transport.request": 0,
"counter.servo.eurekaclient.transport.connectionerrors": 0,
"counter.servo.timeouts": 0,
"counter.servo.rejectedexecutions": 0,
"counter.servo.throwables": 0,
"gauge.servo.threadpoolused": 0,
"gauge.servo.response.metrics": 6,
"normalized.servo.rest.totaltime": 0,
"normalized.servo.rest.count": 0,
"gauge.servo.rest.min": 0,
"gauge.servo.rest.max": 0,
"gauge.servo.eurekaclient.registration.lastheartbeatsec_00030": 0,
"counter.servo.discoveryclient-httpclient_reuse": 10,
"counter.servo.discoveryclient-httpclient_createnew": 26,
"counter.servo.discoveryclient-httpclient_request": 36,
"counter.servo.discoveryclient-httpclient_release": 36,
"counter.servo.discoveryclient-httpclient_delete": 24,
"normalized.servo.discoveryclient-httpclient_requestconnectiontimer.totaltime":
0.005046033333333333,
"normalized.servo.discoveryclient-httpclient_requestconnectiontimer.count":
0.06666666666666667,
"gauge.servo.discoveryclient-httpclient_requestconnectiontimer.min":
0.017749,
"gauge.servo.discoveryclient-httpclient_requestconnectiontimer.max":
0.12356299999999999,
"normalized.servo.discoveryclient-httpclient_createconnectiontimer.totaltime":
0.0012743166666666665,
"normalized.servo.discoveryclient-httpclient_createconnectiontimer.count":
0.05,
"gauge.servo.discoveryclient-httpclient_createconnectiontimer.min":
0.012288,
"gauge.servo.discoveryclient-httpclient_createconnectiontimer.max":
0.034475,
"gauge.servo.connectioncount": 2,
"normalized.servo.eurekaclient.transport.latency.totaltime": 0,
"normalized.servo.eurekaclient.transport.latency.count": 0,
"gauge.servo.eurekaclient.transport.latency.min": 0,
"gauge.servo.eurekaclient.transport.latency.max": 0,
"gauge.servo.response.star-star.favicon.ico": 42,
"gauge.servo.eurekaclient.registry.lastupdatesec_00240": 0,
"gauge.servo.eurekaclient.registration.lastheartbeatsec_00015": 1,
"gauge.servo.response.webjars.star-star": 5,
"gauge.servo.eurekaclient.resolver.endpointssize": 1,
"gauge.servo.eurekaclient.resolver.lastloadtimestamp": 233376,
"gauge.servo.eurekaclient.registration.lastheartbeatsec_00240": 0,
"gauge.servo.eurekaclient.transport.quarantinesize": 0,
"gauge.servo.eurekaclient.registry.lastupdatesec_00030": 0,
"gauge.servo.response.v2.api-docs": 126,
"gauge.servo.eurekaclient.registration.lastheartbeatsec_00480": 0,
"gauge.servo.eurekaclient.registry.lastupdatesec_00480": 0,
"gauge.servo.response.star-star": 13,
"gauge.servo.response.swagger-resources.configuration.ui": 19,
"normalized.servo.eureka-connection-cleaner-time.totaltime": 0.0009386666666666665,
"normalized.servo.eureka-connection-cleaner-time.count": 0.03333333333333333,
"gauge.servo.eureka-connection-cleaner-time.min": 0.021162,
"gauge.servo.eureka-connection-cleaner-time.max": 0.035158,
"counter.servo.eureka-connection-cleaner-failure": 0,
"gauge.servo.eurekaclient.transport.currentsessionduration": 533378,
"gauge.servo.eurekaclient.registration.lastheartbeatsec_00120": 0,
"gauge.servo.eurekaclient.registry.lastupdatesec_00015": 1,
"gauge.servo.response.swagger-resources.configuration.security": 4,
"gauge.servo.eurekaclient.registry.lastupdatesec_00120": 0,
"gauge.servo.response.info": 35,
"gauge.servo.eurekaclient.registration.lastheartbeatsec_00060": 0,
"gauge.servo.eurekaclient.registry.lastupdatesec_00060": 0,
"counter.servo.discoveryclient_reconcilehashcodemismatch": 0,
"normalized.servo.discoveryclient_fetchregistry.totaltime": 0.29706815000000003,
"normalized.servo.discoveryclient_fetchregistry.count": 0.03333333333333333,
"gauge.servo.discoveryclient_fetchregistry.min": 4.337664999999999,
"gauge.servo.discoveryclient_fetchregistry.max": 13.486424,
"counter.servo.discoveryclient_reregister": 0,
"gauge.servo.eurekaclient.registry.localregistrysize": 5,
"gauge.servo.eurekaclient.registry.lastsuccessfulregistryfetchtimeperiod":
22920,
"gauge.servo.eurekaclient.registration.lastsuccessfulheartbeattimeperiod":
22926,
"gauge.servo.response.swagger-resources": 5,
"integration.channel.errorChannel.errorRate.mean": 0,
"integration.channel.errorChannel.errorRate.max": 0,
"integration.channel.errorChannel.errorRate.min": 0,
"integration.channel.errorChannel.errorRate.stdev": 0,
"integration.channel.errorChannel.errorRate.count": 0,
"integration.channel.errorChannel.sendCount": 0,
"integration.channel.errorChannel.sendRate.mean": 0,
"integration.channel.errorChannel.sendRate.max": 0,
"integration.channel.errorChannel.sendRate.min": 0,
"integration.channel.errorChannel.sendRate.stdev": 0,
"integration.channel.errorChannel.sendRate.count": 0,
"integration.channel.springCloudBusInput.errorRate.mean": 0,
"integration.channel.springCloudBusInput.errorRate.max": 0,
"integration.channel.springCloudBusInput.errorRate.min": 0,
"integration.channel.springCloudBusInput.errorRate.stdev": 0,
"integration.channel.springCloudBusInput.errorRate.count": 0,
"integration.channel.springCloudBusInput.sendCount": 0,
"integration.channel.springCloudBusInput.sendRate.mean": 0,
"integration.channel.springCloudBusInput.sendRate.max": 0,
"integration.channel.springCloudBusInput.sendRate.min": 0,
"integration.channel.springCloudBusInput.sendRate.stdev": 0,
"integration.channel.springCloudBusInput.sendRate.count": 0,
"integration.channel.hystrixStreamOutput.errorRate.mean": 0,
"integration.channel.hystrixStreamOutput.errorRate.max": 0,
"integration.channel.hystrixStreamOutput.errorRate.min": 0,
"integration.channel.hystrixStreamOutput.errorRate.stdev": 0,
"integration.channel.hystrixStreamOutput.errorRate.count": 0,
"integration.channel.hystrixStreamOutput.sendCount": 0,
"integration.channel.hystrixStreamOutput.sendRate.mean": 0,
"integration.channel.hystrixStreamOutput.sendRate.max": 0,
"integration.channel.hystrixStreamOutput.sendRate.min": 0,
"integration.channel.hystrixStreamOutput.sendRate.stdev": 0,
"integration.channel.hystrixStreamOutput.sendRate.count": 0,
"integration.channel.nullChannel.errorRate.mean": 0,
"integration.channel.nullChannel.errorRate.max": 0,
"integration.channel.nullChannel.errorRate.min": 0,
"integration.channel.nullChannel.errorRate.stdev": 0,
"integration.channel.nullChannel.errorRate.count": 0,
"integration.channel.nullChannel.sendCount": 0,
"integration.channel.nullChannel.sendRate.mean": 0,
"integration.channel.nullChannel.sendRate.max": 0,
"integration.channel.nullChannel.sendRate.min": 0,
"integration.channel.nullChannel.sendRate.stdev": 0,
"integration.channel.nullChannel.sendRate.count": 0,
"integration.channel.springCloudBusOutput.errorRate.mean": 0,
"integration.channel.springCloudBusOutput.errorRate.max": 0,
"integration.channel.springCloudBusOutput.errorRate.min": 0,
"integration.channel.springCloudBusOutput.errorRate.stdev": 0,
"integration.channel.springCloudBusOutput.errorRate.count": 0,
"integration.channel.springCloudBusOutput.sendCount": 0,
"integration.channel.springCloudBusOutput.sendRate.mean": 0,
"integration.channel.springCloudBusOutput.sendRate.max": 0,
"integration.channel.springCloudBusOutput.sendRate.min": 0,
"integration.channel.springCloudBusOutput.sendRate.stdev": 0,
"integration.channel.springCloudBusOutput.sendRate.count": 0,
"integration.handler._org.springframework.integration.errorLogger.handler.duration.mean":
0,
"integration.handler._org.springframework.integration.errorLogger.handler.duration.max":
0,
"integration.handler._org.springframework.integration.errorLogger.handler.duration.min":
0,
"integration.handler._org.springframework.integration.errorLogger.handler.duration.stdev":
0,
"integration.handler._org.springframework.integration.errorLogger.handler.duration.count":
0,
"integration.handler._org.springframework.integration.errorLogger.handler.activeCount":
0,
"integration.handlerCount": 1,
"integration.channelCount": 5,
"integration.sourceCount": 0,
"httpsessions.max": -1,
"httpsessions.active": 0,
"datasource.primary.active": 0,
"datasource.primary.usage": 0 }
Code flow doesn't even go to the method(tried to use debugger).
The problem with only this newly created endpoint. Last error was
Full authentication is required to access this resource
until I wrote the piece of configuration:
management:
security:
enabled: false
I use
springBootVersion = '1.5.3.RELEASE'
springCloudVersion = 'Dalston.RELEASE'
The issue was with Spring Cloud MetricsInterceptorConfiguration.
As far as I understood, on each endpoint you can add suffix-path /metrics to see the metrics for this endpoint provided by Spring Cloud. So it just intercepted my mapping :)
I solved this by adding the following configuration to bootstrap.yml:
endpoints:
metrics:
enabled: false
I created this arduino sketch and it works fine, what happens is you hold a button down and a pattern of lights plays. You can see my patterns at the bottom. Each button has its own pattern to play when its held.
So this works fine, but I have a question. I'm uneasy about this because I feel that its better practice to keep my patterns outside the program. I want to know, can I store the patterns in a text file that also gets loaded onto the arduino? Is there anyway to put the patterns in a text file, and just read them all onboard the arduino?
const int buttonPin[5] = {8,9,10,11,12};
const int LEDPin[5] = {2,3,4,5,6};
int timer =0;
int millisBegin=0;
boolean reset=true;
boolean run[5] = {false,false,false,false,false};
boolean buttonOn = false;
void setup(){
Serial.begin(57600);
pinMode(buttonPin[0], INPUT);
pinMode(buttonPin[1], INPUT);
pinMode(buttonPin[2], INPUT);
pinMode(buttonPin[3], INPUT);
pinMode(buttonPin[4], INPUT);
pinMode(LEDPin[0], OUTPUT);
pinMode(LEDPin[1], OUTPUT);
pinMode(LEDPin[2], OUTPUT);
pinMode(LEDPin[3], OUTPUT);
pinMode(LEDPin[4], OUTPUT);
}
void loop()
{
for (int x=0; x<6; x++)
{
if (digitalRead(buttonPin[x]) == HIGH)
{
run[x] = true;
}
}
if (run[0] == true)
{
buttonOn = pattern1();
if (buttonOn == false)
{
run[0] = false;
}
}
if (run[1] == true)
{
buttonOn = pattern2();
if (buttonOn == false)
{
run[1] = false;
}
}
if (run[2] == true)
{
buttonOn = pattern3();
if (buttonOn == false)
{
run[2] = false;
}
}
if (run[3] == true)
{
buttonOn = pattern4();
if (buttonOn == false)
{
run[3] = false;
}
}
if (run[4] == true)
{
buttonOn = pattern5();
if (buttonOn == false)
{
run[4] = false;
}
}
}
boolean light(int button, int pattern[][6])
{
while (digitalRead(buttonPin[button])==LOW)
{
reset = true;
for (int x=0; x<5; x++){
digitalWrite(LEDPin[x],LOW);
}
buttonOn = false;
return buttonOn;
}
while (digitalRead(buttonPin[button])==HIGH)
{
if (reset == true)
{
millisBegin = millis();
reset = false;
Serial.println("reset!");
}
timer = millis() - millisBegin;
for (int x=0; x<10; x++) //Pattern amount
{
for (int y=0; y<5; y++) //Lights
{
//if else runs pattern with correct time code
if (timer>pattern[x][5]&&timer<pattern[x+1][5])
{
if (pattern[x][y]==1)
{
digitalWrite(LEDPin[y], HIGH);
}
else
{
digitalWrite(LEDPin[y], LOW);
}
}
}
}
Serial.println(timer);
if (timer > pattern[10][5]){
reset = true;
Serial.println("Over timer!");
}
}
}
boolean pattern1()
{
int pattern[11][6] = {
{0, 0, 0, 0, 0, 100}, //0
{1, 1, 0, 1, 1, 1200}, //1
{0, 0, 1, 0, 0, 2200}, //2
{1, 1, 0, 1, 1, 3200}, //3
{0, 0, 0, 0, 0, 4200}, //4
{1, 1, 1, 1, 1, 5000}, //5
{0, 0, 1, 0, 0, 6000}, //6
{1, 0, 0, 0, 0, 7000}, //7
{0, 1, 0, 1, 1, 8000}, //8arduin
{0, 0, 1, 0, 1, 9000}, //9
{0, 0, 0, 0, 0, 10000}}; //
buttonOn = light(0,pattern);
return buttonOn;
}
boolean pattern2()
{
int pattern[11][6] = {
{1, 0, 1, 0, 0, 100}, //0
{0, 1, 1, 0, 1, 180}, //1
{1, 0, 0, 0, 0, 230}, //2
{0, 1, 0, 1, 1, 340}, //3
{1, 0, 0, 1, 0, 450}, //4
{0, 0, 1, 1, 1, 500}, //5
{0, 0, 1, 0, 0, 550}, //6
{1, 0, 0, 0, 0, 600}, //7
{0, 1, 0, 1, 1, 680}, //8
{0, 0, 1, 0, 1, 800}, //9
{0, 0, 0, 0, 0, 900}}; //
buttonOn = light(1,pattern);
return buttonOn;
}
boolean pattern3()
{
int pattern[11][6] = {
{1, 1, 1, 1, 1, 100}, //0
{0, 0, 0, 0, 0, 180}, //1
{1, 1, 1, 1, 1, 230}, //2
{0, 0, 0, 0, 0, 340}, //3
{1, 1, 1, 1, 1, 450}, //4
{0, 0, 0, 0, 0, 500}, //5
{1, 1, 1, 1, 1, 550}, //6
{0, 0, 0, 0, 0, 600}, //7
{1, 1, 1, 1, 1, 680}, //8
{0, 0, 0, 0, 0, 800}, //9
{0, 0, 0, 0, 0, 810}}; //
buttonOn = light(2,pattern);
return buttonOn;
}
boolean pattern4()
{
int pattern[11][6] = {
{0, 0, 0, 0, 0, 100}, //0
{0, 0, 0, 0, 1, 500}, //1
{0, 0, 0, 1, 1, 800}, //2
{0, 0, 1, 1, 1, 900}, //3
{1, 1, 1, 1, 1, 1000}, //4
{1, 1, 1, 1, 1, 1100}, //5
{1, 1, 1, 1, 0, 1200}, //6
{1, 1, 1, 0, 0, 1300}, //7
{1, 1, 0, 0, 0, 1400}, //8
{1, 0, 0, 0, 0, 1500}, //9
{0, 0, 0, 0, 0, 1600}}; //
buttonOn = light(3,pattern);
return buttonOn;
}
boolean pattern5()
{
int pattern[11][6] = {
{0, 1, 0, 1, 0, 100}, //0
{1, 0, 1, 0, 1, 500}, //1
{0, 1, 0, 1, 0, 800}, //2
{1, 0, 1, 0, 1, 900}, //3
{0, 1, 0, 1, 0, 1000}, //4
{1, 0, 1, 0, 1, 1100}, //5
{0, 1, 0, 1, 0, 1200}, //6
{1, 0, 1, 0, 1, 1300}, //7
{0, 1, 0, 1, 0, 1400}, //8
{1, 0, 1, 0, 1, 1500}, //9
{0, 1, 0, 1, 0, 1600}}; //
buttonOn = light(4,pattern);
return buttonOn;
}
The Arduino boards do not have external storage devices where files can be stored. Of course there are shields with a SD card slot which you can add to your device. This would be overkill however.
But the Arduino has a builtin EEPROM which you can read/write using the EEPROM library.
My suggestion would be:
Extend your program to read and write to USB via Serial. You can then invent some simple text-based commands which allow you to send new patterns to the Arduino.
When the Arduino receives new patterns, it stores them in the EEPROM.
In normal operation mode the Arduino reads the patterns from EEPROM and displays them.
This way you can use your Arduino "standalone" and program it ad-hoc using any computer.