<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Sandip Basnet on Medium]]></title>
        <description><![CDATA[Stories by Sandip Basnet on Medium]]></description>
        <link>https://medium.com/@sandipbasnet?source=rss-d8407c3a89d3------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*tK2cAynx2JrtyvQUBV4huQ.jpeg</url>
            <title>Stories by Sandip Basnet on Medium</title>
            <link>https://medium.com/@sandipbasnet?source=rss-d8407c3a89d3------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 05:05:05 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@sandipbasnet/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[IPFS upload in NodeJs]]></title>
            <link>https://medium.com/@sandipbasnet/ipfs-upload-in-nodejs-a87fd31c671d?source=rss-d8407c3a89d3------2</link>
            <guid isPermaLink="false">https://medium.com/p/a87fd31c671d</guid>
            <category><![CDATA[ipfs-file-upload]]></category>
            <category><![CDATA[web3-storage]]></category>
            <category><![CDATA[nft-storage]]></category>
            <category><![CDATA[nodejs]]></category>
            <dc:creator><![CDATA[Sandip Basnet]]></dc:creator>
            <pubDate>Mon, 06 Mar 2023 05:59:29 GMT</pubDate>
            <atom:updated>2023-03-06T05:59:29.687Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nXMlzBiNi6jc0SEHHv9ZMg.png" /></figure><p>IPFS is a peer-to-peer network for storing and sharing data in a distributed file system. There are various ways for uploading files. Among all using existing websites is the easiest option to try out, but if you want to upload programmatically you have to use APIs. Today I will be explaining two major services that are actively used for IPFS storage.</p><ol><li>Web3 Storage<br>Web3 storage is one of the best services to store data however it has limitations in the free plan as we can only upload up to 5 GiB of files. You can upload files vising the <a href="https://web3.storage/account/">account</a> tab. If you want to upload media using their API, then hover over to the account or <a href="https://web3.storage/tokens/?create=true">visit this link</a> to generate an API key which you can use later</li><li>NFT Storage<br>NFT storage provides free storage for NFTs on IPFS and Filecoin. You can upload files in the <a href="https://nft.storage/files/">Files</a> table after creating an account. Also, we can generate an API key by visiting the <a href="https://nft.storage/manage/">API Keys</a> tab which we will be using in the following section.</li></ol><p><strong>Using Web3 Storage</strong></p><ol><li>Create a project directory:</li></ol><pre>mkdir ipfsupload </pre><p>2. Initialize the project and link it to npm</p><pre>cd ipfsupload<br>npm init -y</pre><p>3. Install express and set up basic routes for file upload.</p><pre>npm i express express-fileupload web3.storage dotenv nodemon</pre><p>Add &quot;type&quot;:&quot;module&quot; in package.json so that we can use module imports</p><p>Folder structure:</p><pre>- server<br>    - controllers<br>    - routes<br>    - temp<br>    - index.js<br>- .env<br>- package.json<br></pre><p>4. Roll up routes and express server</p><p>The final files look like this:</p><p>server/index.js</p><pre>import express from &#39;express&#39;;<br><br>import routes from &#39;./routes/index.js&#39;;<br>const app = express();<br><br>const port = 3000;<br><br>app.get(&#39;/&#39;, (req, res) =&gt; {<br>    res.send(&#39;IPFS upload server is up and running!&#39;);<br>});<br><br> // Mount endpoints<br> app.use(&#39;/api/v1&#39;, routes)<br><br>app.listen(port, () =&gt; console.log(&#39;Server ready at: http://localhost:%s&#39;, port))</pre><p>server/controllers/upload.controller.js</p><pre>import dotenv from &#39;dotenv&#39;;<br>dotenv.config();<br><br>import fs from &#39;fs&#39;<br>import { Web3Storage, File } from &#39;web3.storage&#39;;<br><br>const web3StorageAPIKey = process.env.WEB3_STORAGE_API_KEY;<br><br>function makeStorageClient() {<br>    return new Web3Storage({ token: web3StorageAPIKey });<br>}<br><br>async function makeFileObjects(name, description, image) {<br>    const obj = { name, description, image };<br>    const buffer = Buffer.from(JSON.stringify(obj))<br><br>    const files = [<br>        new File([&#39;contents-of-file-1&#39;], &#39;plain-utf8.txt&#39;),<br>        new File([buffer], &#39;metadata.json&#39;)<br>    ]<br>    return files<br>}<br><br>async function storeFiles(files) {<br>    const client = makeStorageClient()<br>    const cid = await client.put(files)<br>    return cid<br>}<br><br>const fileFromPath = async (image, fileName) =&gt; {<br>    const filePath = image.tempFilePath;<br>    const mimeType = image.mimetype;<br><br>    const content = await fs.promises.readFile(filePath)<br>    const files = [<br>        new File([&#39;contents-of-file-1&#39;], mimeType),<br>        new File([content], fileName)<br>    ]<br>    return files<br>}<br><br><br>const web3StorageUpload = async (req, res) =&gt; {<br>    const { name, description } = req.body;<br>    const { image } = req?.files ?? {};<br>    console.log(`Uploading image: [${name}] to ipfs.`);<br>    try {<br>        if (!image &amp;&amp; !name &amp;&amp; !description || name === undefined) {<br>            return res.status(200).send({ message: &#39;invalid input&#39; });<br>        }<br>        const imageName = `${new Date().getTime()}_${image.name.replaceAll(&#39; &#39;, &#39;&#39;)}`;<br>        const file = await fileFromPath(image, imageName);<br>        const imageCid = await storeFiles(file);<br>        const files = await makeFileObjects(name, description, `https://${imageCid}.ipfs.w3s.link/${imageName}`);<br>        const metaDataCid = await storeFiles(files);<br>        await fs.promises.unlink(image.tempFilePath);<br>        const metadataUrl = `https://${metaDataCid}.ipfs.w3s.link/metadata.json`;<br><br>        const ipfsTierInfo = {<br>            name,<br>            description,<br>            ipfsUrl: metadataUrl,<br>        };<br>        // TODO: store metadata to db<br>        return res.send(ipfsTierInfo);<br>    } catch (error) {<br>        console.log(`Problem while uploading image to ipfs: ${error}`);<br>        return res.status(500).send({<br>            message: &#39;Problem while uploading image to ipfs&#39;<br>        })<br>    }<br>}<br><br>export default {<br>    web3StorageUpload,<br>}</pre><p>server/routes/updalod.route.js</p><pre>import express from &#39;express&#39;;<br>import fileUpload from &#39;express-fileupload&#39;;<br>import controller from &#39;../controllers/upload.controller.js&#39;;<br><br>const router = express.Router();<br>router.use(fileUpload({useTempFiles: true}));<br><br>router.route(&#39;/web3storage&#39;)<br>    .post(controller.web3StorageUpload);<br><br>export default router;</pre><p>server/routes/index.js</p><pre>import express from &#39;express&#39;;<br>import uploadRoute from &#39;./upload.route.js&#39;;<br><br>const router = express.Router();<br><br>// Mount upload endpoints<br>router.use(&#39;/upload&#39;, uploadRoute);<br><br>export default router;</pre><p>.env</p><pre>WEB3_STORAGE_API_KEY=&lt;your_web3_storage_key&gt;</pre><p>5. Now you should be able to start the server and test the file upload from any rest clients.</p><pre>npm run start</pre><p>I am using postman and after successful upload API will respond following message.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/957/1*Sr41JRBi6KiyCHsvXGKG7Q.png" /><figcaption>IPFS upload using web3.storage in NodeJs</figcaption></figure><p><strong>GitHub Repository</strong>: <a href="https://github.com/mondyfy/ipfsupload">IPFS Upload in NodeJs</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a87fd31c671d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[HLS Audio Streaming in NodeJS]]></title>
            <link>https://medium.com/@sandipbasnet/hls-audio-streaming-in-node-js-f89501c86a21?source=rss-d8407c3a89d3------2</link>
            <guid isPermaLink="false">https://medium.com/p/f89501c86a21</guid>
            <dc:creator><![CDATA[Sandip Basnet]]></dc:creator>
            <pubDate>Wed, 29 Jun 2022 17:30:16 GMT</pubDate>
            <atom:updated>2022-06-29T17:53:00.481Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vHmJYi9zjelIKloqV_zkrQ.png" /></figure><p>In this article, I will discuss the working mechanism of HLS and how we can use HLS(HTTP Live Streaming) for audio/music streaming in NodeJs.</p><p><strong>What is HLS?</strong><br>According to Wikipedia: HLS is an <a href="https://en.wikipedia.org/wiki/HTTP">HTTP</a>-based <a href="https://en.wikipedia.org/wiki/Adaptive_bitrate_streaming">adaptive bitrate streaming</a> communications protocol developed by <a href="https://en.wikipedia.org/wiki/Apple_Inc.">Apple Inc</a>. It was released in 2009. Support for the protocol is widespread in media players, web browsers, mobile devices, and streaming media servers.</p><p><strong>Why HLS?</strong></p><ol><li><strong>Fast:</strong> <br>As one large file is divided into segments a few segments in length and those files are fetched on respective player time with the help of the manifest/index file.</li><li><strong>Adaptive Bitrate Streaming: <br></strong>It has the ability to adjust video quality in the middle of a stream as network conditions change. This ability allows videos to keep playing even if network conditions get worse; conversely, it also maximizes video quality to be as high as the network can support. <br>If the network slows down, the user’s video player detects this, and adaptive bitrate streaming lowers the quality of the stream so that the video does not stop playing. If more network bandwidth becomes available, adaptive bitrate streaming improves the quality of the stream.<br>Adaptive bitrate streaming is possible because HLS creates several duplicate segmented streams at different quality levels during the segmentation process. The user’s video player can switch from one of those streams to another one during video playback.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*PfaC000lG2nCWTBiIwupjg.jpeg" /><figcaption>fig: Illustration of Adaptive bitrate streaming. source <a href="https://cloudinary.com/product_updates/plug_and_play_adaptive_bitrate_streaming_with_hls_and_mpeg_dash">cloudinary.com</a>.</figcaption></figure><p>3. Unwanted i.e unwatched or unlistened portions of the file(audio/video) won’t be downloaded.</p><p>4. Less server and client configuration uses HTTP Protocol</p><p><strong>How does HLS work?<br>Server:</strong> An HLS stream originates from a server where (in on-demand streaming) the media file is stored, or where (in live streaming) the stream is created. Because HLS is based on HTTP, any ordinary web server can originate the stream.</p><p>Two main processes take place on the server:</p><ol><li><strong>Encoding:</strong> The audio/video data is reformatted so that any device can recognize and interpret the data. HLS must use <a href="https://www.cloudflare.com/learning/video/what-is-h264-avc/">H.264</a> or H.265 encoding.</li><li><strong>Segmenting:</strong> The audio/video is divided up into segments a few seconds in length.</li></ol><ul><li>In addition to dividing the audio/video into segments, HLS creates an index file of the audio/video segments to record the order they belong in.</li><li>HLS will also create several duplicate sets of segments at different quality levels: 480p, 720p, 1080p, and so on.</li></ul><p><strong>Distribution:</strong> The encoded video segments are pushed out to client devices over the Internet when client devices request the stream. Typically, a CDN or OFS like s3 will help distribute the stream to geographically diverse areas.</p><p><strong>Client devices:</strong> The client device is the device that receives the stream and plays the video — for instance, a user&#39;s smartphone or laptop. The client device uses the index file(.m3u8) as a reference for assembling the audio/video in order, and it switches from higher quality to lower quality pictures (and vice versa) as needed.</p><figure><img alt="hls workflow" src="https://cdn-images-1.medium.com/max/1024/1*TdSkND09q767MfXQmuAvhg.png" /><figcaption>fig: HLS workflow</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*t-g_vUxhL-1rriU1fw25VA.jpeg" /><figcaption>fig: HLS different levels of manifests, source <a href="https://www.streamingmedia.com/Articles/Editorial/What-Is-.../What-Is-HLS-%28HTTP-Live-Streaming%29-78221.aspx?utm_source=related_articles&amp;utm_medium=gutenberg&amp;utm_campaign=editors_selection">https://www.streamingmedia.com/</a></figcaption></figure><p><strong>Example: HLS Audio streaming(NodeJs)<br></strong>1. MP3 to chunks:</p><p>First of all, initiate a project with npm init and add utils/mp3tochunks.js, the contents of mp2tochunks.js should be:</p><pre>const util = require(&#39;util&#39;);<br>const exec = util.promisify(require(&#39;child_process&#39;).exec);<br>const fs = require(&#39;fs&#39;);<br>const path = require(&#39;path&#39;);</pre><pre>const dir = path.join(__dirname, &#39;../songs&#39;);<br>const dest = path.join(__dirname, &#39;../temp/chunks&#39;);</pre><pre>const startTime = new Date();<br>console.info(&#39;&gt; Start reading files&#39;, startTime);</pre><pre>fs.readdir(dir, (readDirError, files) =&gt; {</pre><pre>if (readDirError) {<br>console.error(readDirError);<br>return;<br>}</pre><pre>const countFiles = files.length;</pre><pre>files.map(<em>async</em> (file, index) =&gt; {<br>const fileName = path.join(dir, file);<br>const { err, stdout, stderr } =<br>await exec(`ffmpeg -i ${fileName} -profile:v baseline -level 3.0 -s 640x360 -start_number 0 -hls_time 10 -hls_list_size 0 -f hls  ${dest}/${index}.m3u8`);</pre><pre>if (err) {<br>console.log(err);<br>}</pre><pre>if (countFiles - 1 === index) {<br>const endTime = new Date();<br>console.info(&#39;&lt; End Preparing files&#39;, endTime);<br>}</pre><pre>});<br>});</pre><p>In the above snippet, I have made a <em>song</em> folder that contains mp3 files that will later be converted into chunks and those chunks are stored on the <em>temp/chunks</em> directory.</p><p>The main task in this util is done by <em>ffmpeg, </em>which should be installed on your machine.</p><p>Command used:</p><pre>ffmpeg -i ${fileName} -profile:v baseline -level 3.0 -s 640x360 -start_number 0 -hls_time 10 -hls_list_size 0 -f hls  ${dest}/${index}.m3u8</pre><p><em>where, <br>-i : specifies the input file audio/video,<br>-profile: sets the audio/video encoding codec profiles, setting baseline, as it supports lower-cost applications with limited computing resources,<br>-level: level as mentioned in Annex A of the H.264 standard,<br>-s: sets frame size,<br>-start_number: Set the index of the file matched by the image file pattern to start to read from, the default value is 0.<br>-hls_time: segment duration in seconds,<br>-hls_list_size: Set the maximum number of playlist entries. If set to 0 the list file will contain all the segments. The default value is 5,<br>-f: Set the file format,<br>${dest}/${index}.m3u8: Sets Path of the chunks generated and manifest file m3u8</em></p><p>The content of the m3u8 file should be something like this:</p><pre>#EXTM3U<br>#EXT-X-VERSION:3<br>#EXT-X-TARGETDURATION:10<br>#EXT-X-MEDIA-SEQUENCE:0<br>#EXTINF:10.008778,<br>00.ts<br>#EXTINF:10.008778,<br>01.ts<br>#EXTINF:9.985556,<br>02.ts<br>#EXTINF:10.008778,<br>03.ts<br>#EXTINF:10.008778,<br>04.ts<br>#EXTINF:9.985556,<br>05.ts<br>#EXTINF:10.008778,<br>06.ts<br>#EXTINF:10.008778,<br>07.ts<br>#EXTINF:9.985556,<br>08.ts<br>#EXTINF:10.008778,<br>09.ts<br>#EXTINF:10.008778,<br>010.ts<br>#EXTINF:9.985556,<br>011.ts<br>#EXT-X-ENDLIST</pre><p><em>where,<br></em><strong><em>EXTM3U</em></strong><em>: this indicates that the file is an extended m3u file. Every HLS playlist must start with this tag.</em></p><p><strong><em>EXT-X-VERSION:</em></strong><em> indicates the compatibility version of the Playlist file.</em></p><p><strong><em>EXT-X-TARGETDURATION</em></strong><em>: this specifies the maximum duration of the media file in seconds.</em></p><p><strong><em>EXT-X-MEDIA-SEQUENCE: </em></strong><em>indicates the sequence number of the first URL that appears in a playlist file. Each media file URL in a playlist has a unique integer sequence number. The sequence number of a URL is higher by 1 than the sequence number of the URL that preceded it. The media sequence numbers have no relation to the names of the files.</em></p><p><strong><em>EXTINF</em></strong><em>: tag specifies the duration of a media segment. It should be followed by the URI of the associated media segment — this is mandatory. You should ensure that the EXTINF value is less than or equal to the actual duration of the media file that it is referring to</em></p><p>Once the manifest file is generated, we have to host it, lets add a node server and test it on hls player i.e. add <em>main.js </em>file that should have:</p><pre>var http = require(&#39;http&#39;);<br>var fs = require(&#39;fs&#39;);</pre><pre>const port = 8000</pre><pre>http.createServer(function (request, response) {<br>console.log(&#39;request starting...&#39;);<br>var filePath = &#39;./temp/chunks&#39; + request.url;</pre><pre>fs.readFile(filePath, function(error, content) {<br>response.writeHead(200, { &#39;Access-Control-Allow-Origin&#39;: &#39;*&#39; });</pre><pre>if (error) {<br>if(error.code == &#39;ENOENT&#39;){<br>fs.readFile(&#39;./404.html&#39;, function(error, content) {<br>response.end(content, &#39;utf-8&#39;);<br>});<br>} else {<br>response.writeHead(500);<br>response.end(&#39;Sorry, check with the site admin for error:<br>&#39;+error.code+&#39; ..\n&#39;);<br>response.end();<br>}<br>} else {<br>  response.end(content, &#39;utf-8&#39;);<br>}<br>});<br>}).listen(port);</pre><pre>console.log(`Server running at http://127.0.0.1:${port}/`);</pre><p>This basically takes the request URL and looks for the corresponding URL if that is generated in chunks, if that is generated it will respond with the contents of the file. for example: for request <a href="http://127.0.0.1:8080/0.m3u8"><em>http://127.0.0.1:8000/0.m3u8</em></a><em> </em>the manifest file will be downloaded, here to test the file you have to add one browser extension i.e.<a href="https://chrome.google.com/webstore/detail/native-hls-playback/emnphkkblegpebimobpbekeedfgemhof"> Native HLS Playback</a>, that should play the media you have used. In the meantime, you can inspect the file sequence chunks requested by the client/browser from the server after every 10 seconds the chunk has been loaded.</p><p>That sums up the HLS audio/video streaming with nodejs. Here all the files are served locally, in an ideal case they are served through some online file storage service like AWS s3, for that, I have added <em>uploadchunkstos3.js </em>file in the <a href="https://github.com/mondyfy/hls_demo"><strong><em>repository of this article</em></strong></a><em>.</em></p><p><strong>References</strong></p><ol><li><a href="https://github.com/mondyfy/hls_demo">https://github.com/mondyfy/hls_demo</a></li><li><a href="https://blog.boot.dev/javascript/hls-video-streaming-node/">https://blog.boot.dev/javascript/hls-video-streaming-node/</a></li><li><a href="https://hls-js.netlify.app/demo/">https://hls-js.netlify.app/demo/</a></li><li><a href="https://github.com/video-dev/hls.js/">https://github.com/video-dev/hls.js/</a></li><li><a href="https://scanskill.com/programming/how-to-use-hlsjs-for-video-streaming/">https://scanskill.com/programming/how-to-use-hlsjs-for-video-streaming/</a></li><li><a href="https://www.cloudflare.com/learning/video/what-is-http-live-streaming/">https://www.cloudflare.com/learning/video/what-is-http-live-streaming/</a></li><li><a href="https://medium.com/sharma02gaurav/adaptive-bitrate-streaming-hls-vod-service-in-nodejs-8df0d91d2eb4">https://medium.com/sharma02gaurav/adaptive-bitrate-streaming-hls-vod-service-in-nodejs-8df0d91d2eb4</a></li><li><a href="http://blog.mediacoderhq.com/h264-profiles-and-levels/">http://blog.mediacoderhq.com/h264-profiles-and-levels/</a></li></ol><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f89501c86a21" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Basic Authentication Request in Nodejs]]></title>
            <link>https://medium.com/@sandipbasnet/basic-authentication-request-in-nodejs-7f7cfaf7bf34?source=rss-d8407c3a89d3------2</link>
            <guid isPermaLink="false">https://medium.com/p/7f7cfaf7bf34</guid>
            <category><![CDATA[basic-auth]]></category>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[http-request]]></category>
            <category><![CDATA[request-promise]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Sandip Basnet]]></dc:creator>
            <pubDate>Thu, 26 Sep 2019 19:17:33 GMT</pubDate>
            <atom:updated>2019-09-26T19:21:45.888Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/970/1*FwoltvaEuu4ROxsQcSoFFA.png" /></figure><p>As per <a href="https://en.wikipedia.org/wiki/Basic_access_authentication"><em>Wikipedia</em></a> Basic Authentication is a method for an <a href="https://en.wikipedia.org/wiki/User_agent">HTTP user agent</a> (e.g. a web browser) to provide a <a href="https://en.wikipedia.org/wiki/User_name">user name</a> and <a href="https://en.wikipedia.org/wiki/Password">password</a> when making a request. In basic HTTP authentication, a request contains a header field in the form of Authorization: Basic &lt;credentials&gt;, where credentials is the <a href="https://en.wikipedia.org/wiki/Base64">base64</a> encoding of id and password joined by a single colon :</p><p>The best way I have found is to do the job with <a href="https://www.npmjs.com/package/request-promise">request-promise</a> (The simplified HTTP request client ‘request’ with Promise support.)</p><pre><em>/**<br>* Basic authuthentication request in node<br>* @param {*} username<br>* @param {*} password<br>* @param {*} Method<br>* @param {*} requestURL<br>*/<br></em>async function basicAuthRequestInNode(username,password,Method,requestURL){<br>const jsonData = {<br>key:value,<br>........</pre><pre>}</pre><pre>const auth = &#39;Basic &#39; + new Buffer(username + &#39;:&#39; + password).toString(&#39;base64&#39;);</pre><pre>const options = {<br>headers: {<br>Authorization: auth,<br>&#39;content-type&#39;: &#39;application/json&#39;,},<br>method: Method,<br>body: jsonData,<br>uri: requestURL,<br>json: true,<br>};</pre><pre>try {<br>const response = await rp(options); // rp is request-promise<br>return response;<br>} <br>catch (error) {<br>return error;<br>}<br>}</pre><p>Above function can handle the basic authentication in nodejs.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7f7cfaf7bf34" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Working with connectIPS and Node.js (Part-I]]></title>
            <link>https://medium.com/@sandipbasnet/working-with-connectips-and-node-js-part-i-4fccec456731?source=rss-d8407c3a89d3------2</link>
            <guid isPermaLink="false">https://medium.com/p/4fccec456731</guid>
            <category><![CDATA[crypto]]></category>
            <category><![CDATA[node]]></category>
            <category><![CDATA[request-promise]]></category>
            <category><![CDATA[connectips]]></category>
            <category><![CDATA[pem]]></category>
            <dc:creator><![CDATA[Sandip Basnet]]></dc:creator>
            <pubDate>Thu, 29 Aug 2019 11:38:53 GMT</pubDate>
            <atom:updated>2019-08-29T11:50:57.244Z</atom:updated>
            <content:encoded><![CDATA[<h3>Working with connectIPS and Node.js (Part-I)</h3><p><a href="https://connectips.com/"><em>connect</em> IPS</a> ,said to be a single payments platform that allows the customers to link their bank account(s) to enable payment processor, fund transfer and bill payments. An extended product of Nepal Clearing House to support citizen-to-government (C2G), customer-to-business (C2B) and peer-to-peer (P2P) payment transactions directly from/to the bank accounts.</p><p>First of all any financial organizations get registered on connectIPS and connectIPS provides back with necessary credentials ,now it’s turn of developer to connect connectIPS and their app/product.From the starting of this week i was also trying to do so,finally i made it now, yay!!</p><p>** Probably connectIPS being new to the market doesn’t have good developer support. **</p><p><strong>Talking about development</strong></p><p>I have used request-promise, pem and node-rsa ,we need to use pem for extracting certificate information and private key values from .pfx file .</p><pre><em>// Generate Private Key<br></em>async function generatePrivateKey(pfx) {<br>return new Promise(async (resolve, reject) =&gt; {<br>return pem.readPkcs12(pfx, pkOptions, (err, cert) =&gt; {<br>if (cert) {<br>resolve(cert.key);<br>} <br>else {<br>reject(err);<br>}<br>});<br>});<br>}</pre><p>Response of pem looks similar to</p><pre>{ cert: &quot;...&quot;, ca: [&quot;subca&quot;, &quot;rootca&quot;], key: &quot;...&quot; }</pre><p>Now you can see the information of certificate and private key, as pem returns only the encrypted private key (RSA PRIVATE KEY), but we need to use private key without encryption .Unfortunately pem doesn’t provide this, here we need to convert pkcs12 private key into pkcs8 private key.We can do this with:</p><pre>const pfx = fs.readFileSync(&quot;test.pfx&quot;);<br>const RSAKey = await generatePrivateKey(pfx);<br>const key = new NodeRSA(RSAKey);<br>const privateKey = key.exportKey(&quot;pkcs8&quot;);</pre><p>Now we can use this privateKey to generate hash,</p><pre><em>// Generate Hash<br>/**<br> * @param {[obj]} data [data that you have to send]<br>*/<br></em>async function generateHash(data) {<br>const pfx = fs.readFileSync(&quot;test.pfx&quot;);<br>const RSAKey = await generatePrivateKey(pfx);<br>const key = new NodeRSA(RSAKey);<br>const privateKey = key.exportKey(&quot;pkcs8&quot;);</pre><pre>const signer = crypto.createSign(&quot;sha256WithRSAEncryption&quot;);<br>signer.update(data);<br>const hash = signer.sign(privateKey, &quot;base64&quot;);<br>return hash;<br>}</pre><p>Now we have to send request to connectIPS with following options,</p><pre>const options = await generateOptions(hash, gatewayURL, method);</pre><p>We can get response at:</p><pre>//rp(request-promise)<br>try {<br>const response = await rp(options);<br>return response;<br>} catch (error) {<br>console.log(&quot;error =&gt; &quot;, error);<br>}</pre><p>(…To Be Continued…)</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4fccec456731" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Connecting Raspberry Pi(TS-7970) With LVDS.]]></title>
            <link>https://medium.com/@sandipbasnet/connecting-raspberry-pi-ts-7970-with-lvds-e62463afed3c?source=rss-d8407c3a89d3------2</link>
            <guid isPermaLink="false">https://medium.com/p/e62463afed3c</guid>
            <category><![CDATA[raspberry-pi]]></category>
            <category><![CDATA[lvds]]></category>
            <category><![CDATA[hdmi-to-lvds]]></category>
            <category><![CDATA[lds]]></category>
            <category><![CDATA[ts-7970]]></category>
            <dc:creator><![CDATA[Sandip Basnet]]></dc:creator>
            <pubDate>Fri, 31 May 2019 14:55:43 GMT</pubDate>
            <atom:updated>2019-06-01T07:36:44.698Z</atom:updated>
            <content:encoded><![CDATA[<p>IoT devices are being overwhelmingly used in most of the automated services or products.Life has became much easier because of those devices.As much it is pleasuries to use as hard it is to develop and integrate.Have you ever developed or integrated any of those devices ? If you have done that ,you might be known to the hardships that you have faced for the first time setup .Same was the story for me too . In this article I am going to share how I connected the Raspberry pi with LVDS by customizing and rebuilding the linux kernel specially for TS-7970( but you can use it as an analogy to other devices).</p><h4>Compiling the Kernel</h4><p>This board uses a 4.1.15 Kernel on most of all images and is based on the NXP’s which are changed from upstream for their board support. We have to change them to support the various hardware that we use with this processor.</p><p>The “imx_4.1.15_1.0.0_ga” branch in <a href="https://github.com/embeddedarm/linux-3.10.17-imx6">embeddedarm/linux-3.10.17-imx6</a> includes support for TS-4900, TS-7970, TS-7990, and TS-4100.Also this kernel works with all Debian releases, Ubuntu, Yocto Jethro, and Yocto Krogoth.</p><p>The kernel branch can be selected once the git repository is cloned as outlined below. The kernel can be rebuilt by cross compiling from an X86/X86_64 Linux. The default kernels are rebuilt using the toolchains built by Yocto. You can download the appropriate cross toolchain for your Linux system here:</p><ul><li><a href="/service/ftp://ftp.embeddedarm.com/ts-socket-macrocontrollers/ts-4900-linux/distributions/yocto/morty/toolchain/poky-glibc-x86_64-meta-toolchain-qt5-cortexa9hf-neon-toolchain-2.2.2.sh">x86_64</a></li><li><a href="/service/ftp://ftp.embeddedarm.com/ts-socket-macrocontrollers/ts-4900-linux/distributions/yocto/morty/toolchains/poky-glibc-i686-meta-toolchain-qt5-cortexa9hf-neon-toolchain-2.2.2.sh">i686</a></li></ul><p>Now open your terminal (Assumed root directory here) and do,</p><pre>chmod a+x poky-*toolchain-*.sh<br>sudo ./poky-*toolchain-*.sh</pre><p>This will ask for the install directory for the toolchain. As this instructions assumes that the default path is used.</p><p>This also requires several tools from the host PC linux distribution. For Ubuntu/Debian:</p><pre>sudo apt-get install git build-essential lzop u-boot-tools libncursesw5-dev</pre><p>Once those are installed follow:</p><pre># This will pull our shared kernel, using the 4.1.15 branch, use a folder linux-imx6, and only<br># download the latest changes.<br>git clone <a href="https://github.com/embeddedarm/linux-3.10.17-imx6.git">https://github.com/embeddedarm/linux-3.10.17-imx6.git</a> -b imx_4.1.15_1.0.0_ga linux-imx6 --depth 1</pre><p>Now change the <strong>arch/arm/boot/dts/imx6qdl-ts7970.dtsi </strong>file<strong> </strong>inside <strong>linux-imx6 </strong>folder like:</p><pre>mxcfb1: fb@0 {<br>		compatible = &quot;fsl,mxc_sdc_fb&quot;;<br>		disp_dev = &quot;ldb&quot;;<br>		interface_pix_fmt = &quot;RGB666&quot;;<br>		default_bpp = &lt;16&gt;;<br>		int_clk = &lt;0&gt;;<br>		late_init = &lt;0&gt;;<br>		status = &quot;okay&quot;;<br>	};<br>in the <a href="https://github.com/embeddedarm/linux-tsimx/blob/1cdddde5f71acd177532794e52730f255e1e35ea/arch/arm/boot/dts/imx6qdl-ts7970.dtsi#L98">mxcfb1 node</a> (This change is for redirecting the default display from HDMI to LVDS)</pre><p>Here define ldb( disp_dev = “ldb” ) as:</p><pre>&amp;ldb {<br>	status = &quot;okay&quot;;<br> <br>	lvds-channel@0 {<br>		crtc = &quot;ipu1-di1&quot;;<br>		fsl,data-mapping = &quot;spwg&quot;;<br>		fsl,data-width = &lt;18&gt;;<br>		status = &quot;okay&quot;;<br>		primary;<br> <br>		display-timings {<br>			native-mode = &lt;&amp;timing0&gt;;<br>			timing0: hantronix-svga1 {<br>				clock-frequency = &lt;40000000&gt;;<br>				hactive = &lt;800&gt;;<br>				vactive = &lt;600&gt;;<br>				hback-porch = &lt;46&gt;;<br>				hfront-porch = &lt;210&gt;;<br>				vback-porch = &lt;23&gt;;<br>				vfront-porch = &lt;12&gt;;<br>				hsync-len = &lt;20&gt;;<br>				vsync-len = &lt;10&gt;;<br>				de-active = &lt;1&gt;;<br>				hsync-active = &lt;1&gt;;<br>				vsync-active = &lt;1&gt;;<br>				pixelclk-active = &lt;0&gt;;<br>			};<br>		};<br>	};<br>};</pre><pre>(Note : This is for the 10&quot; Hantronix display used on the TS-TPC-8950:,please customize it according to your LCD )</pre><p>Now,</p><pre>cd linux-imx6<br> <br># These two must be run each time you open a terminal to build the kernel.<br>export CROSS_COMPILE=&quot;/opt/poky/2.2.2/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-&quot;<br># Or if you are using the i686 toolchain:<br># export CROSS_COMPILE=&quot;ccache /opt/poky/2.2.2/sysroots/i686-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-&quot;<br>export ARCH=arm<br>export LOADADDR=0x10008000<br> <br>make ts4900_defconfig<br> <br>## Make any changes in &quot;make menuconfig&quot; or driver modifications, then compile<br>make &amp;&amp; make uImage</pre><h4>Installing the Kernel</h4><p>To install this to an SD card, use a USB SD card reader connected to the host PC.</p><p>(Note: Before installing the kernel in SD card ,first backup the card.</p><p>On Linux, you can use the standard dd tool:</p><pre>sudo dd if=/dev/sdx of=&lt;your backup path&gt;/backup.img</pre><p>or for compression:</p><pre>dd if=/dev/sdx | gzip &gt; /&lt;your backup path&gt;/backup.img</pre><p>Where /dev/sdx is your SD card.</p><p>To correctly identify your card, perform “<strong>df -h</strong>” before and after inserting the SD card and observe the new paths. These new paths represent your SD card.that new path might be /dev/sdb1 or /dev/sdc1. )</p><p>Assuming the SD card has the Linux rootfs set up on “sdc1” do:</p><pre>export DEV=/dev/sdc1<br>sudo mount &quot;$DEV&quot; /mnt/sd</pre><pre># By default your os might not provide the mnt directly and error with can&#39;t point to /mnt/sd might appear ,if that happen then make a directory with mkdir -p /mnt/sd .</pre><pre>sudo rm /mnt/sd/boot/uImage<br>sudo cp arch/arm/boot/uImage  /mnt/sd/boot/uImage<br>sudo cp arch/arm/boot/dts/imx6*ts*.dtb /mnt/sd/boot/<br>INSTALL_MOD_PATH=&quot;/mnt/sd&quot; sudo -E make modules_install <br>INSTALL_HDR_PATH=&quot;/mnt/sd&quot; sudo -E make headers_install<br>sudo umount /mnt/sd/<br>sync</pre><p>The modified kernel is installed in your SD card ,now insert the SD card in your device and start the raspberry pi ,wait for a minute and finally you will figure out your working LVDS display screen …Zomg !!! enjoy it.</p><h4>References</h4><ol><li><a href="https://wiki.embeddedarm.com/wiki/TS-7970#Compile_the_Kernel">https://wiki.embeddedarm.com/wiki/TS-7970#Compile_the_Kernel</a></li></ol><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e62463afed3c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Easy way of adding an existing project to github using CLI.]]></title>
            <link>https://medium.com/@sandipbasnet/easy-way-of-adding-an-existing-project-to-github-using-cli-5c4217ffc73d?source=rss-d8407c3a89d3------2</link>
            <guid isPermaLink="false">https://medium.com/p/5c4217ffc73d</guid>
            <category><![CDATA[github]]></category>
            <category><![CDATA[git-push]]></category>
            <category><![CDATA[git]]></category>
            <dc:creator><![CDATA[Sandip Basnet]]></dc:creator>
            <pubDate>Tue, 07 May 2019 13:16:29 GMT</pubDate>
            <atom:updated>2019-05-16T11:06:39.929Z</atom:updated>
            <content:encoded><![CDATA[<p>If you have existing projects or files already and want to push/publish it on github repo, but not familiar with the git commands for it then following steps will make you complete your task within a minutes.</p><p>Step 1:- First of all visit your github dashboard and then create a repo either private or public but don’t initiate with README and any License Templates,and then click create new repository button, after that you will be redirected to Quick Set up Page, now copy the project URL with HTTPS option.</p><p>Step 2:- Open Terminal and then change the directory to your working or project Directory.</p><p>Step 3:- Initialize your local project as a Git Repository with <br><strong><em>$git init</em> </strong>.</p><p>Step 4:- Add the file to a repository with <strong><em>$git add .</em></strong> , This adds the files of your local repository to staging for your initial commit.</p><p>Step 5:- Commit the files that you have added or staged in your local repository with <strong><em>$git commit -m “your commit message”</em></strong>.</p><p>Step 6:- Now add the URL of your remote repository that you have copied from Quick Setup Page with <strong><em>$git remote add origin &lt; your remote repository URL&gt;</em></strong> and then verify it with <strong><em>$git remote -v</em></strong> .</p><p>Step 7:- Now Push your staged files to remote repository with <strong><em>$git push origin master</em></strong></p><p>After that, you will be asked for Github username and password please provide those credentials, as soon as you enter your password, your local project starts pushing to Github.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5c4217ffc73d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Open Source Tools( Open meet week #3)]]></title>
            <link>https://medium.com/mozilla-ascol/open-source-tools-open-meet-week-3-a8b4e51f971d?source=rss-d8407c3a89d3------2</link>
            <guid isPermaLink="false">https://medium.com/p/a8b4e51f971d</guid>
            <category><![CDATA[open-meet]]></category>
            <category><![CDATA[mozilla-campus-club]]></category>
            <category><![CDATA[mcc-events]]></category>
            <category><![CDATA[mozila-ascol]]></category>
            <category><![CDATA[open-source]]></category>
            <dc:creator><![CDATA[Sandip Basnet]]></dc:creator>
            <pubDate>Sun, 20 Jan 2019 07:18:18 GMT</pubDate>
            <atom:updated>2019-01-20T07:22:00.895Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*YYXiMIUvP4fQhK2v75WnAw.jpeg" /><figcaption>Group Photo After Talk</figcaption></figure><p>Last Saturday (January -5–2019 ) we had a talk on open source tools,softwares,utilities and philosophies. In the event Rameshwor Dhakal Dai from 8th semester(one of the executive member of Mozilla ASCOL) presented different open source tools alternative to paid products.</p><p>Mr. Dhakal also expained in brief about open source software,what it mean?,what it does ?,communities behind it ,activities happening these days and many more.</p><p>Some of the facsimile of the event are :-</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*C07uflHBxRXkEcnJflNxbw.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zgX0cbTP076SCcrP2vTeow.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*m0oGtlztx4p1KOo_NoeQ8A.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*aWdXx4zgp6cj8O-Kr6_uMg.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8oWTZSvHqTluQStdlzwSRQ.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*F38ss5esyb4vBlMGapZ7cw.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5xBNENuXD4AA5NBerdS57w.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TRRiZcQe7vuO7RLjjbqLpw.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jdYlULXaP6fPLpzItxRwTg.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4GgAEZgTdGiDdVaT94S1NQ.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wcOVbhvdeQ4OkvR5B8Jj9Q.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Ym-I6b6oHtg7HTn612SXmg.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*5YdVThCwvYwEek80qiy8pw.jpeg" /><figcaption>Clicks During Event</figcaption></figure><p>About 24 attendees were present on the event from 1st,5th and 8th semester,they were interested in Open Street Mapping among all tools discussed on the session,also they were eager to listen about Toilet Mapping Initiation taken by Kathmandu Living Labs recently. I think we need to have one session soon.<a href="https://www.slideshare.net/SandipBasnet3/open-source-tools-open-source-alternatives-for-paid-toolssoftwareutilities"> Here</a> is the link for the rough slides we have presented in our talk.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a8b4e51f971d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/mozilla-ascol/open-source-tools-open-meet-week-3-a8b4e51f971d">Open Source Tools( Open meet week #3)</a> was originally published in <a href="https://medium.com/mozilla-ascol">Mozilla ASCOL</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Web Scraping With Python (Open Meet Week #2)]]></title>
            <link>https://medium.com/mozilla-ascol/web-scraping-with-python-open-meet-week-2-b29766f1a0a9?source=rss-d8407c3a89d3------2</link>
            <guid isPermaLink="false">https://medium.com/p/b29766f1a0a9</guid>
            <category><![CDATA[mozilla]]></category>
            <dc:creator><![CDATA[Sandip Basnet]]></dc:creator>
            <pubDate>Tue, 25 Dec 2018 15:20:24 GMT</pubDate>
            <atom:updated>2018-12-26T14:01:22.770Z</atom:updated>
            <content:encoded><![CDATA[<p>We,Mozilla Campus Club ASCOL, One of the vibrant tech community have been organizing weekly meetups and workshops.This time (Dec-22–2018),We have organized a workshop on web Scarping with python in the Meeting Hall Of Kathmandu Living Lab. About 26 students from 1st , 3rd ,4th ,6th and 8th semester participated in the workshop.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_Bp1ihoBCvpQSh5OWd5Psw.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*h_WQ_Y6fvfJArRpEi8Nz2A.jpeg" /></figure><p>Program was officially started with the introduction of the Club,it’s members along with it’s gosls and objective by Prajwol Tiwari(an active member of Mozilla ASCOL) and then every participant introduced to other.</p><p>Thoroughly, Mr. Prajwol expained the programming language Python,its current status,Scope,resources to learn it and communities behind it. He justified why newbies should start with python with some satisfying examples. Also he have compared other languages like Java,PHP,R, .Net, React Native etc, their popular frameworks like Spring,Laravel,Flutter etc. with use and applications.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/1*0PwRAjpttv3nKhuibNM0RA.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/1*fPTvXHiCkqO7NZGe3VU_7g.jpeg" /></figure><p>After a while Prajwol shown a demo of web scraping on the news portal using Beautiful Soup, One of the popular module of Python,The session was highly interactive though most of the participants were new comers i.e. from first semester.On the occasion Aayush Paudel(AI enthusiast,<br> City ambassador of nature.ai and one of the community lead of AID for Nepal) has added about different method of scraping on the varying DOM tree of different websites.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GwjVx1QyRtnmIKKIF6i2EQ.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Lh1BbOVfHqG70ElBW0I4uQ.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QwKHKmja3G2r_OzWZXgEgA.jpeg" /></figure><p>In the fullness of time our senior brother Mr. Roshan Gautam (Mozilla Reps) Introduced us about Common Voice project of Mozilla it’s need,importance and impacts. He also described how our contribution matters.</p><p>At last Mr. Nirmal Rijal, Mozilla ASCOL Club Captain summarized the day long work and started discussion for next session. Overall, the event was ended successfully.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*shOnzzjoSY0N8ebhtWIGAQ.jpeg" /><figcaption><strong>Happy participants after the successful workshop</strong></figcaption></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b29766f1a0a9" width="1" height="1" alt=""><hr><p><a href="https://medium.com/mozilla-ascol/web-scraping-with-python-open-meet-week-2-b29766f1a0a9">Web Scraping With Python (Open Meet Week #2)</a> was originally published in <a href="https://medium.com/mozilla-ascol">Mozilla ASCOL</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>