10.13.2021

SimpleDashboard.md

Simplest Blazor IOT Dashboard

Recently I was learning Blazor, here is the first taste.

Demo :

Step

  1. Create a “Blazor Server Application” project.
  2. Named it “BlazorIOTDemo” or whatever you like.
  3. Add “MyDataDto.cs” in Data folder.
    public class MyDataDto
    {
        public int Id { get; set; }
        public int Value { get; set; }
    }
    
  4. Add “DataService.cs” in Data folder.
    public class DataService
     {
         public DataService()
         {
             this._timer = new Timer(UpdateValues, null, this._updateInterval, this._updateInterval);
         }
    
    
         public event EventHandler<List<MyDataDto>> DataChanged;
    
    
         private Timer _timer;
         private readonly TimeSpan _updateInterval = TimeSpan.FromMilliseconds(1000);
    
    
         private void UpdateValues(object state)
         {
             var myDataDtos = new List<MyDataDto>
             {
                new MyDataDto() { Id = 1, Value = new Random().Next(1, 80) },
                new MyDataDto() { Id = 2, Value = new Random().Next(10, 80) },
                new MyDataDto() { Id = 3, Value = new Random().Next(20, 80) },
                new MyDataDto() { Id = 4, Value = new Random().Next(30, 80) },
                new MyDataDto() { Id = 5, Value = new Random().Next(40, 80) },
                new MyDataDto() { Id = 6, Value = new Random().Next(50, 80) },
                new MyDataDto() { Id = 7, Value = new Random().Next(60, 80) }
             };
    
    
             DataChanged?.Invoke(this, myDataDtos);
         }
     }
    
  5. Configure service in "Startup.cs"

    It’ll be better to use interface.

    services.AddSingleton<DataService>();
    
  6. Alter the content in “Index.razor” to this
  7. @page "/"
    @using BlazorIOTDemo.Data
    @inject DataService DataService
    @if (myDatasDtos == null)
    {
    <p><em>Loading datas...</em></p>
    }
    else
    {
    <div class="container">
    <div class="row">
    <div>
    <table class="table">
    <thead>
    <tr>
    <th>Id</th>
    <th>Value</th>
    </tr>
    </thead>
    <tbody>
    @foreach (var item in myDatasDtos)
    {
    <tr>
    <td>@item.Id</td>
    <td>@item.Value</td>
    </tr>
    }
    </tbody>
    </table>
    </div>
    <div>
    <RadzenChart>
    <RadzenLineSeries Data="@myDatasDtos" CategoryProperty="Id" ValueProperty="Value">
    <RadzenMarkers MarkerType="MarkerType.Circle" />
    </RadzenLineSeries>
    </RadzenChart>
    </div>
    </div>
    </div>
    }
    @code {
    protected override async Task OnInitializedAsync()
    {
    DataService.DataChanged += ServerDataChanged;
    }
    List<MyDataDto> myDatasDtos;
    private async void ServerDataChanged(object sender, List<MyDataDto> newDatas)
    {
    await InvokeAsync(() =>
    {
    Console.WriteLine("received data.");
    myDatasDtos = newDatas;
    StateHasChanged();
    });
    }
    }

Project structure:

9.28.2021

speedupSt.md

Use autohotkey to speedup st programming.

As the poor support for structure text programming in plc world(code snippet), here are some short key for it I used with autohotkey.

It’s good for your healthy, enjoy it.

  • ,s ==> SET(TRUE, );
  • ,r ==> RST(TRUE, );
  • ,t ==> := TRUE;
  • ,f ==> := FALSE;
  • ;====================================
    ; for ladder
    ;====================================
    ; key 'a ' => 'ld '
    :*:a ::ld
    :*:b ::ldi
    :*:o ::out
    ;====================================
    ; for structure text
    ;====================================
    ; key ',f' --> ' := FALSE;'
    :*:,f:: := FALSE;
    ; key ',t' --> ' := TRUE;'
    :*:,t:: := TRUE;
    ; key ',;' --> ' := ;'
    :*:,;:: := 0;{Left 2}
    :*:,s::SET(TRUE, );{Left 2}
    :*:,r::RST(TRUE, );{Left 2}
    :*:,ei::END_IF;
    ; replace c sytle mark '//' to '(* *)'
    :://::(* *){Left 3}
    ; three '-' --> 'seperate line'
    ; 輸入三個"-"後,會變成一列分割線
    ::---::(*-------------------------------------------------------------------------------------------------*)
    ; '/todo' --> '(* TODO: *)'
    ; 輸入/todo後,變成 (* TODO: *)
    ::/todo::(* TODO: *){Left 3}
    ; generate 'if' block
    ::/if::If THEN{Enter}{Tab};{Enter}END_IF;{UP 2}
    ; generate 'case' block
    ::/cas::CASE ( ) OF{Enter}:{Enter}{Tab 2};{Enter}END_CASE;{UP 3}
    ; comment a block
    ; use hotkey "ctrl +'/'" to add (* *) surround the target string
    ^/::
    Send ^c(*{Enter}^v{Enter}*)
    return
    ; change "M0 := false;" --> "RST(TRUE, M0);"
    ; use hotkey ctrl + '.' to change boolean assign style
    ^.::
    Send {Home}
    Send +{End}
    Clipboard = ;
    Send ^c
    ClipWait, 2
    srcString = %Clipboard%
    wordsAry := StrSplit(srcString, [A_Space, ";"])
    tmpString := wordsAry[1]
    str1 := wordsAry[3]
    StringUpper, upStr, str1
    if (upStr = "TRUE")
    {
    Clipboard = SET(TRUE, %tmpString%);
    }
    if (upStr = "FALSE")
    {
    Clipboard = RST(TRUE, %tmpString%);
    }
    Send +{Left 1}
    Send ^v
    ClipWait, 2
    Send {Home}
    Send {Tab}
    return
    ; generate Today's datetime string
    ::,d::
    d = %A_YYYY%/%A_MM%/%A_DD%
    Send %d%
    return
    ;Win + Ctrl + R reload script
    #^r::
    reload
    return
是否追蹤此瀏覽器的瀏覽量 ?
目前設定:追蹤 修改
(本區塊只有網站管理者看得到)