I have just learned how to use sci-chart framework with tutorials.
And I tried to add values from bluetooth as realtime chart as shown in tutorials.
I have finished receiving data from a Bluetooth connection.
However, using scichart to represent this data in real time is hard to solve by looking at the tutorial alone.
Does anyone have any idea how to use real-time tutorials to teach you how to represent your own data, not the example sine graph?
The code below is what I tried and is wrong.
import UIKit
import CoreBluetooth
import SciChart
let maestroServiceCBUUID = CBUUID(string:”495sdfd3-FE7D-4AE5-8FA9-9FAFD205E455″)
let maestroBrainDataCBUUID = CBUUID(string: “4953sdf3-1E4D-4BD9-BA61-23C647249616”)
class HRMViewController: UIViewController {
var sciChartSurface: SCIChartSurface?
var lineDataSeries: SCIXyDataSeries!
var scatterDataSeries: SCIXyDataSeries!
var lineRenderableSeries: SCIFastLineRenderableSeries!
var scatterRenderableSeries: SCIXyScatterRenderableSeries!
var timer: Timer?
var phase = 0.0
var i = 0
@IBOutlet weak var brainRateLabel: UILabel!
var centralManager: CBCentralManager!
var maestroPeripheral:CBPeripheral!
override func viewDidLoad() {
super.viewDidLoad()
sciChartSurface = SCIChartSurface(frame: self.view.bounds)
sciChartSurface?.autoresizingMask = [.flexibleHeight, .flexibleWidth]
sciChartSurface?.translatesAutoresizingMaskIntoConstraints = true
self.view.addSubview(sciChartSurface!)
let xAxis = SCINumericAxis()
xAxis.growBy = SCIDoubleRange(min: SCIGeneric(0.1), max: SCIGeneric(0.1))
sciChartSurface?.xAxes.add(xAxis)
let yAxis = SCINumericAxis()
yAxis.growBy = SCIDoubleRange(min: SCIGeneric(0.1), max: SCIGeneric(0.1))
sciChartSurface?.yAxes.add(yAxis)
createRenderableSeries()
addModifiers()
centralManager = CBCentralManager(delegate: self , queue: nil)
// Make the digits monospaces to avoid shifting when the numbers change
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if nil == timer{
timer = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true, block: updatingDataPoints)
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if nil != timer{
timer?.invalidate()
timer = nil
}
}
func updatingDataPoints(timer:Timer){
i += 1
lineDataSeries.appendX(SCIGeneric(i), y: SCIGeneric(cos(Double(i)*0.1 + phase)))
scatterDataSeries.appendX(SCIGeneric(i), y: SCIGeneric(cos(Double(i)*0.1 + phase)))
phase += 0.01
sciChartSurface?.zoomExtents()
sciChartSurface?.invalidateElement()
}
func createDataSeries(_brainwave2:Double){
// Init line data series
lineDataSeries = SCIXyDataSeries(xType: .double, yType: .double)
lineDataSeries.fifoCapacity = 500
lineDataSeries.seriesName = “line series”
// Init scatter data series
// scatterDataSeries = SCIXyDataSeries(xType: .double, yType: .double)
// scatterDataSeries.fifoCapacity = 500
// scatterDataSeries.seriesName = “scatter series”
for i in 0...500{
lineDataSeries.appendX(SCIGeneric(i), y: SCIGeneric(_brainwave2))
// scatterDataSeries.appendX(SCIGeneric(i), y: SCIGeneric(cos(Double(i)*0.1)))
}
i = Int(lineDataSeries.count())
}
func createRenderableSeries(){
lineRenderableSeries = SCIFastLineRenderableSeries()
lineRenderableSeries.dataSeries = lineDataSeries
scatterRenderableSeries = SCIXyScatterRenderableSeries()
scatterRenderableSeries.dataSeries = scatterDataSeries
sciChartSurface?.renderableSeries.add(lineRenderableSeries)
sciChartSurface?.renderableSeries.add(scatterRenderableSeries)
}
func addModifiers(){
let xAxisDragmodifier = SCIXAxisDragModifier()
xAxisDragmodifier.dragMode = .pan
xAxisDragmodifier.clipModeX = .none
let yAxisDragmodifier = SCIYAxisDragModifier()
yAxisDragmodifier.dragMode = .pan
let extendZoomModifier = SCIZoomExtentsModifier()
let pinchZoomModifier = SCIPinchZoomModifier()
let rolloverModifier = SCIRolloverModifier()
let legend = SCILegendModifier()
let groupModifier = SCIChartModifierCollection(childModifiers: [xAxisDragmodifier, yAxisDragmodifier, pinchZoomModifier, extendZoomModifier, legend, rolloverModifier])
sciChartSurface?.chartModifiers = groupModifier
}
func brainwaveReceived(_ brainWave:Double){
let brainWave = brainWave * 3.3 / 65536
brainRateLabel.text = String(brainWave)
print(“brainwave: (brainWave)”)
}
}
extension HRMViewController: CBCentralManagerDelegate {
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .unknown:
print("central.state is . unknown")
case .resetting:
print("central.state is . resetting")
case .unsupported:
print("central.state is . unsupported")
case .unauthorized:
print("central.state is . unauthorized")
case .poweredOff:
print("central.state is . poweredOff")
case .poweredOn:
print("central.state is . poweredOn")
centralManager.scanForPeripherals(withServices:nil)
}
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
print(peripheral)
if peripheral.name == “MAESTRO1” {
// maestroPeripheral = peripheral
centralManager.stopScan()
maestroPeripheral = peripheral
maestroPeripheral.delegate = self
central.connect(maestroPeripheral)
}
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
print(“Connected!”)
maestroPeripheral.discoverServices([maestroServiceCBUUID])
}
}
extension HRMViewController:CBPeripheralDelegate{
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
guard let services = peripheral.services else {return}
for service in services {
print(service)
peripheral.discoverCharacteristics(nil, for: service)
}
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
guard let characteristics = service.characteristics else {return}
for characteristic in characteristics {
print(characteristic)
if characteristic.properties.contains(.read){
print("\(characteristic.uuid): properties contain .read")
}
if characteristic.properties.contains(.notify){
print("\(characteristic.uuid): properties contain .notify")
peripheral.setNotifyValue(true , for: characteristic)
}
}
}
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic,
error: Error?) {
switch characteristic.uuid {
case maestroBrainDataCBUUID:
let wave = Double(brainData(from: characteristic))*3.3/65536
createDataSeries(_brainwave2:wave)
default:
print("Unhandled Characteristic UUID: \(characteristic.uuid)")
}
}
private func brainData(from characteristic: CBCharacteristic) -> Int {
guard let characteristicData = characteristic.value else { return -1 }
let byteArray = UInt8
let firstBitValue = byteArray[0] & 0x01
if firstBitValue == 0 {
// Heart Rate Value Format is in the 2nd byte
return Int(byteArray[1])
} else {
// Heart Rate Value Format is in the 2nd and 3rd bytes
return (Int(byteArray[1]) << 8) + Int(byteArray[2])
}
}
}
- JaeHwan Seol asked 7 years ago
- You must login to post comments
Hi JaeHwan,
The code sample above – we can’t run that and have a look so its hard to see what is wrong when someone pastes so much code into the forums.
All I can suggest to you, is from the tutorial (which you’ve seen here), you need to use a technique like this to append data into the DataSeries.
func updatingDataPoints(timer:Timer){
let i = lineDataSeries.count()
lineDataSeries.appendX(SCIGeneric(i), y: SCIGeneric(sin(Double(i)*0.1 + phase)))
scatterDataSeries.appendX(SCIGeneric(i), y: SCIGeneric(cos(Double(i)*0.1 + phase)))
phase += 0.01
sciChartSurface?.zoomExtents()
}
SCIXyDataSeries.appendX function allows you to append an X,Y value to the data series. The chart will automatically redraw but it will not zoom to fit unless you call SCIChartSurface.zoomExtents() or you set SCIAxisBase.autoRange.
let me know if this helps
Best regards
Andrew
- Andrew Burnett-Thompson answered 7 years ago
- You must login to post comments
First of all ,
Thank you for answer about my question.
But , i still can’t solve this problem.
What i want to make likes as below (y value : cos or sin(Double(i)) -> wave)
Wave is from bluetooth data
But if i tried to that , there were some error.
How to apply to wave in another function to y value in scichart? (refer to tutorials)
It might be just normal customizing chart.. But i’m not sure how to solve it ..TT
Thank you
func updatingDataPoints(timer:Timer){
i += 1
lineDataSeries.appendX(SCIGeneric(i), y: SCIGeneric(wave)))
phase += 0.01
sciChartSurface?.zoomExtents()
sciChartSurface?.invalidateElement()
}
func createDataSeries(){
lineDataSeries = SCIXyDataSeries(xType: .double, yType: .double)
lineDataSeries.fifoCapacity = 500
lineDataSeries.seriesName = "line series"
for i in 0...500{
lineDataSeries.appendX(SCIGeneric(i), y: SCIGeneric(wave))
}
i = Int(lineDataSeries.count())
}
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic,
error: Error?) {
switch characteristic.uuid {
case maestroBrainDataCBUUID:
let wave = Double(brainData(from: characteristic))*3.3/65536
default:
print("Unhandled Characteristic UUID: \(characteristic.uuid)")
}
}
- JaeHwan Seol answered 7 years ago
- You must login to post comments
Please login first to submit.