{"id":4343,"date":"2018-12-12T20:00:56","date_gmt":"2018-12-12T19:00:56","guid":{"rendered":"https:\/\/msalamon.pl\/?p=4343"},"modified":"2025-12-27T20:05:28","modified_gmt":"2025-12-27T19:05:28","slug":"addressable-ws2812b-leds-on-stm32-part-3","status":"publish","type":"post","link":"https:\/\/msalamon.pl\/en\/addressable-ws2812b-leds-on-stm32-part-3\/","title":{"rendered":"Addressable WS2812B LEDs on STM32, Part 3"},"content":{"rendered":"\n<p>We have reached the end of the series on WS2812B addressable LEDs. At least for now. In this part, I will discuss splitting an LED strip into fully configurable and independent segments. This means that each segment can operate in a different mode, at a different speed, and have a different length. This gives huge possibilities to tailor it to your needs. Let\u2019s go!<\/p>\n\n\n\n<!--more-->\n\n\n\n<p>This article is part of the series:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"http:\/\/msalamon.pl\/adresowalne-diody-ws2812b-na-stm32-cz-1\/\">Part 1<\/a><\/li>\n\n\n\n<li><a href=\"http:\/\/msalamon.pl\/adresowalne-diody-ws2812b-na-stm32-cz-2\/\">Part 2<\/a><\/li>\n\n\n\n<li><a href=\"http:\/\/msalamon.pl\/adresowalne-diody-ws2812b-na-stm32-cz-3\/\">Part 3<\/a><\/li>\n<\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><a href=\"https:\/\/sklep.msalamon.pl\/kategoria-produktu\/dev-boardy\/stm32-nucleo\/?utm_source=blog&amp;utm_medium=banner&amp;utm_campaign=ws2812b&amp;utm_content=nucleo\"><img loading=\"lazy\" decoding=\"async\" width=\"1200\" height=\"400\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/Nucleo-64-baner.jpg\" alt=\"\" class=\"wp-image-1593\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/Nucleo-64-baner.jpg 1200w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/Nucleo-64-baner-300x100.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/Nucleo-64-baner-1024x341.jpg 1024w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/Nucleo-64-baner-768x256.jpg 768w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<h1 class=\"wp-block-heading\">The idea of splitting into segments<\/h1>\n\n\n\n<p>Since LED strips can theoretically be infinitely long, it would be a shame to waste their potential on setting up just one effect. You can route such a strip in different places, bend it, and do other tricks. For example, when lining a cabinet under the TV, we wouldn\u2019t necessarily want every edge to glow in the same way. That\u2019s why I modified the <a href=\"https:\/\/github.com\/lamik\/WS2812B_STM32_HAL\" target=\"_blank\" rel=\"noopener\">library<\/a>&nbsp;and added segment splitting to it. The Arduino library that inspired me also has this capability, but it is implemented in a slightly different way.<\/p>\n\n\n\n<p>One of my assumptions was dynamically creating the appropriate array of segments. Thanks to this, if you want only one segment, only one \u201cobject\u201d of a segment is created in memory. The number of segments can be changed on the fly. The code ensures there are no memory leaks and the segment array scales on an ongoing basis. One segment occupies 56 bytes in memory and looks like this:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">typedef struct ws2812bfx_s\n{\n\tvolatile uint32_t ModeDelay; \/\/ Segment SW timer counter\n\n\tuint16_t IdStart; \/\/ Start segment point\n\tuint16_t IdStop; \/\/ End segment point\n\n\tuint8_t Running : 1; \/\/ Is sector running\n\tuint8_t ActualMode; \/\/ Sector mode setting\n\tuint8_t Reverse : 1; \/\/ Is reverted mode\n\tuint32_t CounterModeCall; \/\/ Numbers of calls\n\tuint32_t CounterModeStep; \/\/ Call step\n\n\tuint16_t Speed; \/\/ Segment speed\n\n\tuint32_t ModeColor[NUM_COLORS]; \/\/ Mode color 32 bit representation\n\tws2812b_color ModeColor_w[NUM_COLORS]; \/\/ Mode color struct representation\n\n\tuint8_t AuxParam; \/\/ Computing variable\n\tuint16_t AuxParam16b; \/\/ Computing variable\n\tuint8_t Cycle : 1; \/\/ Cycle variable\n\n\tvoid (*mModeCallback)(void); \/\/ Sector mode callback\n} ws2812bfx_s;<\/pre>\n\n\n\n<p>I am aware that some parameters are redundant for certain modes. Fortunately, this is not a huge cost. I will optimize it in the future as needed.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Library fundamentals<\/h2>\n\n\n\n<p>For proper operation, the library requires software&nbsp;<em>timers<\/em> and a callback in the main loop.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">void WS2812BFX_SysTickCallback(void);<\/pre>\n\n\n\n<p>I place the SysTick callback in the predefined SysTick callback located in the HAL libraries. Since it is a&nbsp;<em>weak<\/em> function, I conveniently put it in the fourth user code section of the&nbsp;<em>main.c<\/em> file. This is similar to the previous version of the library.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">void WS2812BFX_Callback(void);<\/pre>\n\n\n\n<p>The FX library callback function, similar to the previous version, handles invoking subsequent effects. It must be placed in the main loop.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Creating segments<\/h3>\n\n\n\n<p>In the example, I split the entire strip into 3 segments. After initializing LED control, you need to call the effect initialization using the function<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">FX_STATUS WS2812BFX_Init(uint8_t Segments);\n<\/pre>\n\n\n\n<p>This function sets up the array of structures responsible for segments. It takes as an argument the number of segments into which the strip will be divided. This function divides the strip into equal parts. The function can also add another segment while remembering the settings of all previous ones. Removing a segment causes the information about the last one to be irretrievably lost, while every new segment above the previous count has default settings and is paused \u2013 you need to start it. For convenient addition and removal of segments, you can use the prepared functions.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">FX_STATUS WS2812BFX_SegmentIncrease(void);\nFX_STATUS WS2812BFX_SegmentDecrease(void);\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Segment configuration<\/h3>\n\n\n\n<p>Alright, but I\u2019d like different lengths for these segments. I anticipated that with several convenient functions.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">FX_STATUS WS2812BFX_SegmentIncreaseEnd(uint8_t Segment);\nFX_STATUS WS2812BFX_SegmentDecreaseEnd(uint8_t Segment);\nFX_STATUS WS2812BFX_SegmentIncreaseStart(uint8_t Segment);\nFX_STATUS WS2812BFX_SegmentDecreaseStart(uint8_t Segment);\n<\/pre>\n\n\n\n<p>As the names suggest, with them we can move the first and last point within a segment. These operations are safe and do not allow two neighboring segments to overlap. Therefore, for example, to increase segment no. 1 at the end, you must first move the start of segment no. 2.<\/p>\n\n\n\n<p>There is one more, less safe function.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">FX_STATUS WS2812BFX_SetSegmentSize(uint8_t Segment, uint16_t Start, uint16_t Stop);<\/pre>\n\n\n\n<p>It no longer prevents segments from overlapping. I didn\u2019t implement guarding for a simple reason. Everyone may imagine shifting a neighboring segment differently. Because what should be done when the neighboring segment already has only one LED? Remove it or shorten another one? Or maybe shorten all segments evenly as you expand? I leave that to you, and with this function you can freely configure the lengths of individual effects.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Setting colors<\/h3>\n\n\n\n<p>Each mode requires at least one color to operate. The maximum number of colors required by any mode is 3. Each has its own ID by which it can be referenced. A color can be set in four ways.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">void WS2812BFX_SetColorStruct(uint8_t id, ws2812b_color c);\nvoid WS2812BFX_SetColorRGB(uint8_t id, uint8_t r, uint8_t g, uint8_t b);\nvoid WS2812BFX_SetColorHSV(uint8_t id, uint16_t h, uint8_t s, uint8_t v);\nvoid WS2812BFX_SetColor(uint8_t id, uint32_t c);\n<\/pre>\n\n\n\n<p>The effect of calling any of the above functions is the same.&nbsp;<strong>Note<em> <\/em><\/strong><em>\u2013<\/em><em>&nbsp;<\/em>these functions assign the color to temporary variables. To apply them to a specific segment, you must afterward call the function that starts the selected operating mode on the given segment.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Operations on modes<\/h3>\n\n\n\n<p>Changing the mode of individual segments seems to be the most important function in the operation of a WS2812B LED strip.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">FX_STATUS WS2812BFX_SetMode(uint8_t Segment, fx_mode Mode);\nFX_STATUS WS2812BFX_NextMode(uint8_t Segment);\nFX_STATUS WS2812BFX_PrevMode(uint8_t Segment);\nFX_STATUS WS2812BFX_SetReverse(uint8_t Segment, uint8_t Reverse);<\/pre>\n\n\n\n<p>The names, as usual, speak for themselves. You can set a specific mode for a selected segment or choose the next or previous mode. The functions do not allow you to go beyond the list of available modes.<\/p>\n\n\n\n<p>The last two functions concern setting the direction of the animation for some modes, either one way or the other.<\/p>\n\n\n\n<p>Besides changing modes, the library allows you to control the operation of a given segment.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">FX_STATUS WS2812BFX_Start(uint8_t Segment);\nFX_STATUS WS2812BFX_Stop(uint8_t Segment);\n<\/pre>\n\n\n\n<p>These functions start or stop the animation on the selected segment. At the moment of start, the mode\u2019s&nbsp;<em>timers&nbsp;<\/em>are reset and the colors stored in the temporary color settings variables are assigned \u2013 the segment will run from the beginning rather than continue from the stop point.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Animation speed<\/h3>\n\n\n\n<p>The animation speed for each segment is set separately using the functions below.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">FX_STATUS WS2812BFX_SetSpeed(uint8_t Segment, uint16_t Speed);\nFX_STATUS WS2812BFX_IncreaseSpeed(uint8_t Segment, uint16_t Speed);\nFX_STATUS WS2812BFX_DecreaseSpeed(uint8_t Segment, uint16_t Speed);\n<\/pre>\n\n\n\n<p>The value of <em>Speed<\/em> in the first function is expressed in milliseconds between each step in a mode. The exceptions are two modes \u2013&nbsp;<em>FX_MODE_WHITE_TO_COLOR<\/em> and <em>FX_MODE_BLACK_TO_COLOR<\/em> \u2013 for which this value is the time needed for the transition black\/white -&gt; color -&gt; black\/white, also expressed in milliseconds.<\/p>\n\n\n\n<p>The last two functions increase the already set speed in the segment by the value from the <em>Speed<\/em> argument.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Collecting information about segments<\/h3>\n\n\n\n<p>For the purposes of external communication, e.g., via UART or USB, there is a need to remotely check the configuration of the entire strip controller.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">uint8_t WS2812BFX_GetSegmentsQuantity(void);\nFX_STATUS WS2812BFX_IsRunning(uint8_t Segment, uint8_t *Running);\nFX_STATUS WS2812BFX_GetMode(uint8_t Segment, fx_mode *Mode);\nFX_STATUS WS2812BFX_GetReverse(uint8_t Segment, uint8_t *Reverse);\nFX_STATUS WS2812BFX_GetSegmentSize(uint8_t Segment, uint16_t *Start, uint16_t *Stop);\nFX_STATUS WS2812BFX_GetSpeed(uint8_t Segment, uint16_t *Speed);\nFX_STATUS WS2812BFX_GetColorRGB(uint8_t id, uint8_t *r, uint8_t *g, uint8_t *b);\n<\/pre>\n\n\n\n<p>All these functions return the appropriate operating parameters of the strip and segments. They return them via the pointers provided in the arguments. As you can see, each function returns an FX_STATUS value. This is related to the successful execution of the function. FX_STATUS has two states.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">typedef enum {\n  FX_OK = 0,\n  FX_ERROR = 1\n} FX_STATUS;\n<\/pre>\n\n\n\n<p>FX_ERROR, as is easy to guess, indicates an error. For example, it may be an out-of-range error. Such an error will occur when trying to read the mode of segment no. 7 while only 5 are active.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Example<\/h2>\n\n\n\n<p>I recorded a video that showcases the operation of segments and their configuration. For this purpose, I implemented USB communication via a <em>virtual COM port&nbsp;<\/em>and simple message parsing. Please don\u2019t pay attention to the correctness of the parsing because there are many ways to do it, and the one I implemented here is quite primitive.<\/p>\n\n\n\n<p><iframe width=\"560\" height=\"315\" loading=\"lazy\" src=\"https:\/\/www.youtube.com\/embed\/qLGGCYQSWJs\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen=\"allowfullscreen\"><\/iframe><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p>As I mentioned in the first paragraph, for now this is the end of the series on WS2812B addressable LEDs. As possibilities and reader feedback allow, I will fix possible bugs and implement interesting proposals. I encourage you to send me your ideas.<\/p>\n\n\n\n<p>Splitting an LED strip into segments offers amazing customization options. I will probably set something up on the window or on the Christmas tree during the upcoming holidays. I also see the use of segments in interior or furniture decoration. Only our imagination limits us \ud83d\ude09<\/p>\n\n\n\n<p>Thank you for reading this post. If you like this kind of topic, let me know in the comments. I would also be grateful for suggestions of topics you\u2019d like me to cover.<\/p>\n\n\n\n<p>The code is, as usual, available on my GitHub: <a href=\"https:\/\/github.com\/lamik\/WS2812B_STM32_HAL\" target=\"_blank\" rel=\"noopener\">link<\/a><\/p>\n\n\n\n<p><span>If you have noticed any error, disagree with something, would like to add something important, or simply want to discuss this topic, write a comment. Remember that the discussion should be polite and in accordance with the rules of the Polish language.<\/span><\/p>\n\n\n\n<p>This article is part of the series:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"http:\/\/msalamon.pl\/adresowalne-diody-ws2812b-na-stm32-cz-1\/\">Part 1<\/a><\/li>\n\n\n\n<li><a href=\"http:\/\/msalamon.pl\/adresowalne-diody-ws2812b-na-stm32-cz-2\/\">Part 2<\/a><\/li>\n\n\n\n<li><a href=\"http:\/\/msalamon.pl\/adresowalne-diody-ws2812b-na-stm32-cz-3\/\">Part 3<\/a><\/li>\n<\/ul>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;4343&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;0&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;0&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;0&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;0\\\/5 - (0 votes)&quot;,&quot;size&quot;:&quot;24&quot;,&quot;title&quot;:&quot;Addressable WS2812B LEDs on STM32, Part 3&quot;,&quot;width&quot;:&quot;0&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} - ({count} {votes})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 0px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 19.2px;\">\n            <span class=\"kksr-muted\"><\/span>\n    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>We have reached the end of the series on WS2812B addressable LEDs. At least for now. In this part, I will discuss splitting an LED strip into fully configurable and independent segments. This means that each segment can operate in a different mode, at a different speed, and have a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3029,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[160],"tags":[176,174,177],"class_list":["post-4343","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-stm32","tag-programming","tag-stm32","tag-stm32cubemx"],"_links":{"self":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts\/4343","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/comments?post=4343"}],"version-history":[{"count":3,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts\/4343\/revisions"}],"predecessor-version":[{"id":4453,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts\/4343\/revisions\/4453"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/media\/3029"}],"wp:attachment":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/media?parent=4343"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/categories?post=4343"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/tags?post=4343"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}