2021年7月17日 星期六

Setting up ARC between Onkyo amplifier and Panasonic TV

Background

Want to try the functionality of using ARC to pass through TV audio to Onkyo 626 amplifier to output sound

Problems

After configuring settings in amplifier and TV, the audio is still not playing through my speakers

Solutions

One of the device (media player EGreat A5) is blocking the ARC signal, disconnecting it with the Onkyo amplifier make things work normally

Set-up sharing

Panasonic P55VT50H

  • Press remote button "Option", configure VIERA Link as "On"
  • You will find "Home theatre" selection in Application section

Onkyo NR626

  • The output channel should be selected with "TV/CD"
  • The main TV out of amplifier (Out 1) should connect with Panasonic TV's (TV in 2)
  • Advanced Settings > Input / Output Assign > Digital Audio Input > TV / CD, configure it as "--"
  • Advanced Settings > Source Setup > Audio Selector configured as "ARC"
  • Advanced Settings > Hardware Setup > HDMI,HDMI CEC (RIHD) configured as "ON" and Audio Return Channel configured as "Auto"

References

2021年7月10日 星期六

React concepts and learning

1. Usage of useRef

  • Syntax: const refObj = useRef(initialVal), where refObj={current: initialVal}
  • refObj is mutable
  • Value persists through the react lifetime (even after you changed the initialVal)
  • Use cases
    • Managing DOM directly, e.g.: textfield focus, integrate with 3rd party DOM libraries
      • <input ref={textInput} type="text" />, where const textInput = useRef(null) is declared on top of the functional component, by accessing textInput, you retrieve the input DOM element for further processing
    • Store instance variables
      • Use to store setInterval or setTimeout's ID for clearing at unmount stage. 
        • const intervalRef = useRef(null);
        • intervalRef.current = setInterval(() => { // something... });
        • clear stuffs in return function of useEffect return () => { clearInterval(intervalRef) }
    • Use as render counter when you want to know how many re-render made by React (since ref values keep throughout the React lifetime)
2. Usage of useMemo

3. Usage of useCallback

References

4. About useEffect and rendering timing
useEffect always run after the UI rendering is done, the useEffect will check the dependecy array against the value of the last render, and run the useEffect callback when they are different from each other.

References

2021年6月12日 星期六

Anywhere maintenance & troubleshooting cheat sheet

Useful Command

1. Remove node's log  

rm -rf /mnt/logs

2. Stream content of p2_ha log continuously

tail -f /mnt/logs/p2ha.log

3. Dump troubleshooting statistics for bug fixing

dumpStat.sh

4. Get neighbor from neighbor table

cat /sys/kernel/p2_nbr/nbr_tbl_dump

5. Restart syslogd when log is not outputting for some reasons

/etc/init.d/syslogd restart

6. View p2 routing protocol information

p2rp_cli -u -D

7. To find packets to and from eth1 interface filtered with only port 16001 related 

tcpdump -i eth1 -p 16001

Useful Meta Data

1. Log path of launcher in Windows

C:\Program Files\Anywhere Node Manager Launcher\user_data\logdata


Troubleshooting Notes

Scenario 1: In A-NM, you find node information of any nodes not showing up in mesh topology after performing node recovery (given the lost node is physically on)

Procedure

1. Check console log http response output to compare the result with UI behavior

2. Check whether the node is in managed device list (Note: node recovery failure may cause lost node being unamanged)

3. If 1. returns fail to retrieve, get the reason of failure, try to map the failure object with the error object documented in "doc_ui_p2_controller", try to resolve through the detailed error message returned from the controller

4. Try to isolate the problem from UI using "controller_restful_tester", run get-nodeinfo command to the remote node from the controller, if success, connection of controller <--> node should be good

5. Try to further isolate the issue from controller by directly retreiving node information using protobuf tool. Remember to run the meshTopology command first to achieve the access port of the remote node first

& '<pythonEXE_dir>' .\cli\ha.py --pw mgnt_pwd mgnt_ip -p access_port 1 > mesh_topology.txt

The "1" refers to the request type, no need to place the whole action name

6. If in 5, we still cannot get the result, troubleshoot, in host node, using tcpdump, data-network packet anaylzer to at least confirm packets are flowing normally between controller <---> host_node and host_node <--> remote_node with their perspective interfaces and ports

e.g.:

Let's say we have a controller (10.240.2.34), a host node (10.240.222.224) and a remote node. 

First we run "tcpdump -i eth1 port 16001" on host node to ensure packet is running to remote node through host node (as 16001 is the NAT port of the remote node), if there are packets routing through port 16001, it implies there are some traffic from 10.240.222.224 to the remote node through the ethernet port connecting between controller

Then we run "tcpdump -i mesh0 port 12381" on remote node, making sure packet is coming to and from the remote node

If the result is positive, we can be sure the layer 3 and layer 4 connectivity is working as expected.

7. Next, use command 4 to make sure neighbor link can be discovered in both nodes


Scenario 2: Capturing logs and output to other parties for bug fixing

1. Before capturing any logs, we need to make sure time stamp of 1) Node 2) Controller and 3) UI is in sync first.

2. For node to sync time, navigate to cluster configuration, and set the timezone to Hong Kong, reboot of nodes in cluster to apply the changes

3. Navigate to system settings, configure the ntp server (IP only, same L2 environment). Therefore we should find a PC (better Linux based), install the ntpd and configure with the HK time server first before proceeding 4) 

4. Login to the cluster and run "date" command on all nodes make sure their time is in sync with the time server you have configured in 3)

5. Since controller and UI should share the same time (Windows system time), just make sure they are in sync with the Windows time should be fine

6. Navigate to /mnt/logs to remove all logs from the target nodes

7. Remove all controller logs in "C:\Program Files\Anywhere Node Manager Launcher\user_data\logdata"

8. 

Miscellaneous Materials

1. SNAT, DNAT and masquerade

https://www.huaweicloud.com/articles/90a13a644803d0efcd024df76fb130ae.html

2021年6月5日 星期六

Frequently used web programming / design techniques

1. Use "data-*" to pass data to event listener

There are many times we need to pass parameters to the event listeners but may not want to use bind or arrow function to prevent frequent unnecessary re-rendering in React, in this case we can add "data-*" html attribute to accomplish.

e.g.: 

<a href="#someLink" onCLick={onClickHandler}>
  <span data-idx={valToOnclickListener}>someSpanText</span>
</a>

Then in "onClickHandler" function, we can use event object "e" to retrieve the data-idx parameter we would like to make use for further processing in this way.

const onClickHandler = (e) => {
  const valToOnclickListener = e.target.dataset.idx;

  // do anything here with valToOnclickListener

}

Sometimes the listener will capture the child element even though you actually put the "data-idx" attribute to the parent, in this case use e.currentTarget,  the target capture must be the one which attaches the listener.


2. Specify child DOM using JSS

Use > to specify the child, use together with the class name, e.g.:

{
  someClassName: {
        '& > :first-child': {
                borderLeft: '2px solid transparent',
         }
    }
}


References

2021年5月18日 星期二

Multi-container restaurant project

Background

A project includes a restaurant owner who wants to deploy our online ordering system with all his restaurants (total 8) to include online ordering features, currently, only a static page goldenthumb.com.hk is running (with https enabled), our target is to use a single AWS lightsail instance to serve for 

1. Providing portal page (run by Gatsby JS), currently goldenthumb.com.hk, act as a portal page to allow user to quickly select different restaurants for ordering, reference site: https://www.maximsmx.com.hk/takeaway_promotion/?utm_source=eatizen

2. Use subdomain to distinguish different restaurants, e.g. lck.goldenthumb.com.hk is the ordering system of restaurant located at Lai Chi Kok

3. api.lck.goldenthumb.com.hk is the API URL served by loopback JS container to provide RESTful service to access database (mongoDB)'s data

4. Run in https and able to check and renew the cert automatically

5. Provide ftp access for the static goldenthumb.com.hk file updates for site maintenance










Problems

This project setup is very much similar to another post, but more complicated, as it includes 2 more containers, certbot and static portal page container which co-exists with the nginx, loopback, mongo express, mongoDB containers (the ordering web application formation) as well as the ftp container and another nginx container.

The following are the problems I have faced during the system configuration

1. The lck.goldenthumb.com.hk requests are not forwarded to the desired nginx container, showing "502 bad gateway"

Turns out I have wrongly restart the container that is never meant to be restarted, normally the static web container "goldenthumbStatic" is used as the main server to receive client requests, the proxy_server settings should be configured inside "goldenthumbStatic" as follows

server {
  # Serving api url for internal use
  server_name lck.goldenthumb.com.hk;
  
  ssl_certificate /etc/letsencrypt/live/goldenthumb.com.hk/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/goldenthumb.com.hk/privkey.pem;
  
  listen 80 ;
  listen 443 ssl ;
  
  # access_log /var/log/nginx/access.loopback.log;
  # We redirect all outside request to appropriate loopback container
  location / {
    proxy_pass http://lck.goldenthumb.com.hk;
  }

  location /admin {
    proxy_pass http://lck.goldenthumb.com.hk;
    try_files $uri /index.html;
  }

  location /.well-known/acme-challenge/ {
    root /var/www/certbot;
  }
}

The location / block is important, it tells the server when request comes as "lck.goldenthumb.com.hk", then forward the request to server block "http://lck.goldenthumb.com.hk", which is defined below 

# Groups of server for proxy_pass usage in below server block
upstream lck.goldenthumb.com.hk {
  # We put docker container service name (internal docker IP) for pointing to right API server (8082:80)
  server frontend;
}

Here the upstream block is used to define blocks of server(s) for reference of proxy_pass directives, the value in proxy_pass is related to this upstream block and forward the request to frontend.

Although configurated correctly, I keep restarting the wrong docker container which the settings are therefore yet to apply 

2. The api.lck.goldenthumb.com.hk requests are not forwarded to the desired loopback container, showing "Connection refused"

This is turn out a silly mistake which forgot to update loopback configuration file (config.json), 80 port should be configured to accept the API connections from other containers

3. The admin management page lck.goldenthumb.com.hk/admin is not working, showing "Connection refused"

The nginx conf is not configured correctly, below is the corrected config, the "try_files" is important to guide nginx server to query original index.html when api.lck.goldenthumb.com.hk/admin is navigated, and let react route to handle the rest of the routing tasks instead of the server itself

  location /admin {
    proxy_pass http://lck.goldenthumb.com.hk;
    try_files $uri /index.html;
  }

4. The APIs used in admin page all fired as "lck.goldenthumb.com.hk/xxx" which is different from expected "api.lck.goldenthumb.com.hk/xxx"

This is due to the wrongly configured dockerfile setup, missing a step to copy the compiled js files to the production docker container, causing the updated code not reflecting the changes.

5. The https certbot challenges for multiple subdomains

HTTPS needs to apply for every sub-domain, lck.goldenthumb.com.hk, api.lck.goldenthumb.com.hk needs to be applied separately, update the certbot script (init-letsencrypt.sh) first, with domain marked to all desired sub-domains

domains=(goldenthumb.com.hk www.goldenthumb.com.hk lck.goldenthumb.com.hk api.lck.goldenthumb.com.hk)

Then in docker compose file, configure the all container volumes which need https certificates by adding /var/www/certbot to accept the challenges

./app/certbot/www:/var/www/certbot


2021年5月16日 星期日

MySQL learning notes

 Queries

1. Create simple tables

CREATE TABLE IF NOT EXISTS Menus (
    id VARCHAR(20) NOT NULL,
    filename VARCHAR(30),
    PRIMARY KEY(id)
) DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS Restaurant (
    id VARCHAR(20) NOT NULL,
    name VARCHAR(20) NOT NULL,
    address VARCHAR(100),
    isOpen BOOLEAN,
    menu VARCHAR(20),
    PRIMARY KEY (id),
    FOREIGN KEY(menu) REFERENCES Menus(id)
) DEFAULT CHARSET=utf8;

2. Update existing column's (from not null to null)

ALTER TABLE Menus MODIFY filename VARCHAR(30) NULL;